核心数据保存和加载到多个实体

Posted

技术标签:

【中文标题】核心数据保存和加载到多个实体【英文标题】:Core Data Saving and Loading to Multiple Entities 【发布时间】:2011-03-11 02:08:59 【问题描述】:

核心数据新手在这里。

我有一个项目,它将数据保存到单个实体没有问题。但是,由于实体的属性太多(超过 100 个),它会收到警告,我需要对其进行规范化。好的,所以我创建了第二个实体,以双向存储更多数据。

问题是当我尝试保存数据时,数据会保存并重新加载到第一个实体,但不会从第二个实体保存或重新加载。我一定错过了一些简单的东西。

这里有一些代码:

//ViewDidLoad
    - (void)viewDidLoad

    if (managedObjectContext == nil) 
        managedObjectContext = [(CoreDataStuffAppDelegate *) [[UIApplication sharedApplication] delegate] managedObjectContext];
        NSLog(@"After managedObjectContext: %@", managedObjectContext);
    

   // [self addRecord];
    [super viewDidLoad];

    if ([self fetchData]) 
        NSLog(@"after self fetchData patientArray count is %i", [parentArray count]);
        if ([parentArray count] == 1) 
            Parent *parentInfo = (Parent *)[parentArray objectAtIndex:0];
            parentItem1.text = parentInfo.Mother;
            NSLog(@"fetching on load %i", [parentArray count]);

            //Try 1:  just going after the relationship route (FAIL:  cuz data wont store.  stays null)
         //   childItem1.text = parentInfo.ParentToChild.Kid;

              // Try 2:  going the route of directly talking to the second entity
            childItem1.text = child.Kid;
        
    

// Save Record
    - (void)saveRecord
    if (managedObjectContext == nil) 
        NSLog(@"there is no context, arrg");

    
    NSLog(@"array count is %i", [parentArray count]);
    if ([parentArray count] == 1) 
        NSManagedObjectContext *context = managedObjectContext;//[parent managedObjectContext];
        NSLog(@"context 1 is: %@", context);

        Parent *parentInfo = (Parent *)[parentArray objectAtIndex:0];
        parentInfo.Mother = parentItem1.text;
        NSLog(@"data says: %@", parentInfo.Mother);
        NSLog(@"text syas: %@", parentItem1.text);

        // Try 1, save it through the child relationship thing.  (failed)
    //    parentInfo.ParentToChild.Kid = childItem1.text;
    //    NSLog(@"childSave says: D: %@ T: %@", parentInfo.ParentToChild.Kid , childItem1.text);

       // Try 2.  from Resipeas app
        if (!child) 
            self.child = [NSEntityDescription insertNewObjectForEntityForName:@"Child" inManagedObjectContext:context];
            [parent addChildObject:child];
            NSLog(@"I hit the child");

        
        child.Kid = childItem1.text;
        NSLog(@"1: childSave says: D: %@ T: %@", parentInfo.ParentToChild.Kid , childItem1.text);
        NSLog(@"2: childSave says: D: %@ T: %@", child.Kid , childItem1.text);



        NSError *error = nil;
        if (![context save:&error]) 
            NSLog(@"context 2 is: %@", context);
            NSLog(@"major fail %@", [error localizedDescription]);
         //   abort();
        
    
    NSLog(@"saving stuff");



// FetchData
- (BOOL)fetchData 
    NSLog(@"doing the fetch");
    BOOL returnResult = FALSE;
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    if (managedObjectContext == nil) 
     
        NSLog(@"ok making a new managed object context");
        managedObjectContext = [(CoreDataStuffAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; 
    

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Parent" inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entity];
    [fetchRequest setFetchBatchSize:1];
    NSError *error;
    NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];
    if (mutableFetchResults == nil) 
        NSLog(@"Fetching Error");
     else 
        [self setParentArray:mutableFetchResults];
        returnResult = TRUE;
        NSLog(@"Fetching went well");
    

    [mutableFetchResults release];
    [fetchRequest release];

    return (returnResult);

【问题讨论】:

【参考方案1】:

好的,首先,我认为您在这里有一个概念问题,因为我从未见过需要具有 100 个属性的实体。大多数实体都有大约六个属性,我认为我见过的最多的是 20 个左右。

Core Data 首先是一个对象图管理系统,具有持久性作为选项。它旨在实现模型-视图-控制器(MVC)设计的模型层。因此,Core Data 主要是关于建模数据而不是存储它。

实体旨在表示一些现实世界的对象、条件或事件。现实世界中没有很多具有 100 个属性的事物。例如。你想制作一个人的详细模型。你想要名字,姓氏,地址(每个地址组件的属性),驾驶执照#和签发日期,地址的工作地点,社会安全号码等。如果你试图把所有这些都塞进一个@987654321 @entity 你最终可能会得到几十个属性。但是,如果您仔细查看您正在建模的数据以及数据中的关系,您会注意到在现实世界中,地址、驾驶执照、工作地点等实际上并不是真实人物的属性,而是其他真实对象的属性真实的人有关。因此,最好的方法是将这些对象的属性分解为单独的实体并创建与 Person 实体的关系。这也使模型更加逼真。毕竟,不止一个人可以住在同一个地址或在同一个地方工作。

因此,您可能需要从头开始,重新考虑您的数据模型设计。

确保您了解实体和 managedObjects 之间的区别。实体是抽象的,仅用于定义 managedObjects 的键、值类型和关系。实体之于 managedObjects 就像类之于实例一样。

你还有两个问题:

(1) 如果您为实体定义了自定义 NSManagedObject 子类,则只能使用点语法访问器形式,例如 parentInfo.ParentToChild.Kid。否则,您使用的是通用 NSManagedObject 实例,并且必须使用键值方法,例如[parent setvalue:forKey].

(2) 提取只返回一个实体的对象。因此,如果您有一个父实体和一个子实体。每个 fetch 返回 Parent 或 Child 的实例,但绝不会同时返回两者(除非它们都继承自 fetch 的实体。)

【讨论】:

第一。感谢您抽出宝贵时间给出如此完整的答案。我同意,在这种情况下,把关于“病人”的一切都塞进去是错误的做法。但是,当我尝试创建多个实体(例如将信息分解成相关的小块)时,我无法将数据保存到除一个实体之外的所有实体。但是,您的评论(2)让我思考。我想我只对“父母”进行一次提取,而不是其他人,这可能是我的问题之一。 我很高兴重新设计我的模型,事实上我很想这样做,只是在为如何一次将数据提取和保存到多个实体而苦苦挣扎。再次感谢您的帮助。欢迎任何关于如何与多个实体交谈和回信的进一步想法。 我认为你不理解关系的概念。关系允许您获取一个实体的对象,然后使用关系访问相关实体的对象。例如。您有一个 Patient 实体和一个与此 PatientDoctor 相关的 Doctor 实体。每个 Patient 对象有一个 Doctor,但每个 Doctor 可能有多个患者。如果您想了解特定的 Patient 医生,您可以获取该特定的 Patient 对象,然后检查其 Patient.doctor 关系以了解有关该医生的所有信息。以此类推。 只获取一个对象然后用它来查找与获取的对象相关的数十个或数百个其他对象是很常见的。例如,患者实体可能具有护士、历史、currentChart、mealPreferences、过敏、保险等的互惠关系。要查找拥有特定保险的所有患者,您将获取该特定保险对象,然后查看患者中的患者对象关系。 要添加数据,您只需反转该过程。如果您有一个新患者,您可以创建一个新的 Patient 对象,然后使用 fetches 来查找现有的单个 Doctor 对象、Nurse 对象、Insurance 对象等,然后将这些对象添加到该特定 Patient 对象的适当关系中。

以上是关于核心数据保存和加载到多个实体的主要内容,如果未能解决你的问题,请参考以下文章

核心数据不保存一个实体的属性

核心数据添加和检索到多个表如何

如何将来自多个视图控制器的数据保存到单个核心数据实体中

保存核心数据相关数据并使用具有多个实体的 NSPredicate 和 NSFetchedResultsController 检索

保存已编辑的核心数据实体未保存

将部分核心数据保存到云端