Xcode4核心数据关系

发布于 2024-11-17 15:54:12 字数 2485 浏览 1 评论 0原文

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

三个表:

  • ZipData
  • LocationData
  • CrossReference

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 中没有任何内容)。我知道我错过了一些关系方面的事情,但我无法指出它。

I've once again read through the Apple developer Core Data documentation and found it lacking when it comes to the graphical Xcode 4 editor when creating SQLLite entities much as I found it lacking when IB was separate in Xcode 3.

Three tables:

  • ZipData
  • LocationData
  • CrossReference

CrossReference has the primary key of ZipData and LocationData so I only need to query CrossReference to get all zips for locations or all locations for zips. This means of course a to-many relationship on both ZipData and LocationData (and perhaps on CrossReference?).

What I have (that isn't working) relationship-wise is this :

  • ZipData has a relationship "locations" that points to LocationData and is inverse
  • LocationData has a relationship "zipsCodes" that points to ZipData and is inverse
  • CrossReference table has two relationships, one to ZipData (and is inverse) and one to LocationData (and is inverse).

I'm not sub-classing any of the entities as NSManagedObjects just yet. I am simply doing the code below in the viewDidLoad method, just to see if what I have setup works.

// 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];

I don't understand how to setup these relationships and not sure how to trust that somehow the primary keys are setup and the entities just kind of find their way together.

I'm getting nothing back in the logs even though when I view the simulators sqllite db I see the test entities have been persisted (but nothing in CrossReference). I know I'm missing something relationship wise but I can't put my finger on it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

酒儿 2024-11-24 15:54:12

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

我再次通读了Apple
开发人员核心数据文档和
发现它缺乏
创建时的图形 Xcode 4 编辑器
SQLLite 实体 就像我发现的那样
当 IB 在 Xcode 中分离时缺少
3.

三个表:

ZipData 位置数据交叉引用

交叉引用的主键
ZipData 和 LocationData 所以我只
需要查询 CrossReference 才能得到
地点的所有邮政编码或所有
拉链的位置。

不存在 SQLite 实体这样的东西,并且 Core Data 没有表或主键。

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

您正在犯一个 SQL 技术人员常犯的错误。您假设 Core Data 是过程 SQL 的轻量级对象包装器。它不是。 SQLite 存储只是四个持久性选项之一,数据模型本身完全独立于您选择的持久性选项,即相同的模型适用于所有类型的存储。这些商店只是对活动对象的图表进行归档和解除归档(冷冻干燥和重新水化)的不同方式。特定图如何持久化是在绝大多数情况下您可以忽略的幕后实现细节。简单地忘记你所知道的关于 SQL 的一切,因为它不会帮助你理解核心数据。

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

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

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

掌握核心数据的关键是忽略持久化的形式,而只考虑具有属性和关系的对象。一旦你真正内化了这个概念,那么一切就很容易实现了。

Your major problem is revealed by the bolded phrases below:

I've once again read through the Apple
developer Core Data documentation and
found it lacking when it comes to the
graphical Xcode 4 editor when creating
SQLLite entities much as I found it
lacking when IB was separate in Xcode
3.

Three tables:

ZipData LocationData CrossReference

CrossReference has the primary key of
ZipData and LocationData so I only
need to query CrossReference to get
all zips for locations or all
locations for zips.

There is no such thing as SQLite entities and Core Data does not have tables or primary keys.

Core Data is not SQL. Entities are not tables. Objects are not rows. Attributes are not columns. Relationships are not joins. Core Data is an object graph management system that may or may not persist the object graph and may or may not use SQL far behind the scenes to do so. Trying to think of Core Data in SQL terms will cause you to completely misunderstand Core Data and result in much grief and wasted time.

You are making a mistake common to people skilled in SQL. You are assuming that Core Data is a lightweight object wrapper around procedural SQL. It is not. The SQLite store is but one of four persistence options and the data model itself is wholly independent of which persistence option you choose i.e. the same model will work with all types of stores. The stores are just different means of archiving and de-archiving (freeze drying and rehydrating) a graph of live objects. How a specific graph gets persisted is a behind the scenes implementation detail you can ignore in the vast majority of cases. Simply forget everything you know about SQL because it won't help you understand Core Data.

Your specific problem here is that you never set the relationships between the objects. You need to create a CrossReference object and set it's relationships, thusly;

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

The context will ensure that the reciprocal relationship is set on the related LocationData and ZipData objects.

The key to mastering Core Data is to ignore the form of persistence and to instead think only in terms of objects with attributes and relationships. Once you really internalize that concept, then every thing falls into place easily.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文