2

我再次通读了 Apple 开发人员 Core Data 文档,发现它在创建 SQLLite 实体时缺少图形 Xcode 4 编辑器,就像我在 Xcode 3 中分离 IB 时发现它所缺少的一样。

三张表:

  • 压缩数据
  • 位置数据
  • 交叉引用

CrossReference 具有 ZipData 和 LocationData 的主键,因此我只需要查询 CrossReference 即可获取位置的所有 zip 或 zip 的所有位置。这当然意味着 ZipData 和 LocationData 上的一对多关系(也许在 CrossReference 上?)。

我所拥有的(那是行不通的)关系方面是这样的:

  • ZipData 有一个关系“位置”,它指向 LocationData 并且是反向的
  • LocationData 有一个关系“zipsCodes”,它指向 ZipData 并且是反向的
  • CrossReference 表有两种关系,一种与 ZipData(并且是反向的)和一种与 LocationData(并且是反向的)的关系。

我还没有将任何实体子分类为 NSManagedObjects。我只是在 viewDidLoad 方法中执行下面的代码,只是为了看看我的设置是否有效。

// test/learn the core data frame work
NSManagedObjectContext *context = [self managedObjectContext];
NSManagedObject *locationData = [NSEntityDescription
                                   insertNewObjectForEntityForName:@"LocationData" 
                                   inManagedObjectContext:context];
[locationData setValue:@"Testville" forKey:@"City"];
[locationData setValue:@"United Tests" forKey:@"Country"];
[locationData setValue:@"County of Test" forKey:@"County"];
NSManagedObject *zipCodeData = [NSEntityDescription
                                      insertNewObjectForEntityForName:@"ZipCodeData" 
                                      inManagedObjectContext:context];
[zipCodeData setValue:[NSNumber numberWithDouble:1111.00] forKey:@"Income"];
[zipCodeData setValue:[NSNumber numberWithDouble:22.00] forKey:@"LandArea"];
[zipCodeData setValue:@"23060" forKey:@"ZipCode"];
NSError *error;
if (![context save:&error]) {
    NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
}

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription 
                               entityForName:@"CrossReference" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *info in fetchedObjects) {
    NSLog(@"LocationId: %@", [info valueForKey:@"LocationDataId"]);
    NSManagedObject *details = [info valueForKey:@"details"];
    NSLog(@"ZipId: %@", [details valueForKey:@"ZipCodeDataId"]);
}        
[fetchRequest release];

我不明白如何设置这些关系,也不知道如何相信主键已设置好,而实体只是找到了一起的方式。

即使当我查看模拟器 sqllite db 时我看到测试实体已被持久化(但在 CrossReference 中没有任何内容),我在日志中什么也没有得到。我知道我在关系方面错过了一些东西,但我不能指望它。

4

1 回答 1

7

您的主要问题由下面的粗体短语揭示:

我再次通读了 Apple 开发人员 Core Data 文档,发现它在创建 SQLLite 实体时缺少图形 Xcode 4 编辑器,就像我在 Xcode 3 中分离 IB 时发现它所缺少的一样。

三张表:

ZipData LocationData CrossReference

CrossReference 具有 ZipData 和 LocationData 的主键,因此我只需要查询 CrossReference 即可获取位置的所有 zip 或 zip 的所有位置。

没有这样的东西SQLite entities,Core Data 没有表或主键。

核心数据不是 SQL。实体不是表格。对象不是行。属性不是列。关系不是连接。Core Data 是一个对象图管理系统,它可能会也可能不会持久化对象图,并且可能会或可能不会在幕后使用 SQL 来做到这一点。试图用 SQL 术语来思考 Core Data 会导致你完全误解 Core Data 并导致很多痛苦和浪费时间。

你犯了一个对 SQL 技术熟练的人来说很常见的错误。您假设 Core Data 是围绕过程 SQL 的轻量级对象包装器。它不是。SQLite 存储只是四个持久性选项之一,数据模型本身完全独立于您选择的持久性选项,即相同的模型将适用于所有类型的存储。这些存储只是对活体图形进行归档和解归档(冷冻干燥和再水化)的不同方式。在大多数情况下,您可以忽略特定图表的持久化方式是幕后实现细节。只需忘记您对 SQL 的所有了解,因为它不会帮助您理解 Core Data。

您在这里的具体问题是您从未设置对象之间的关系。因此,您需要创建一个CrossReference对象并设置它的关系;

  NSManagedObject *crossReference = [NSEntityDescription
                                   insertNewObjectForEntityForName:@"CrossReference" 
                                   inManagedObjectContext:context];     
  [crossReference setValue:locationData forKey:@"location"]; 
  [crossReference setValue:zipCodeData forKey:@"zipCode"];

上下文将确保在相关对象LocationDataZipData对象上设置互惠关系。

掌握 Core Data 的关键是忽略持久性的形式,而只考虑具有属性和关系的对象。一旦你真正内化了这个概念,那么每件事都很容易就位。

于 2011-06-29T19:54:39.917 回答