iOS SDK 上的错误或我对继承实体关系的误解?

Posted

技术标签:

【中文标题】iOS SDK 上的错误或我对继承实体关系的误解?【英文标题】:Bug on iOS SDK or my misconception on relationship of inheritance entity? 【发布时间】:2011-08-26 16:01:24 【问题描述】:

我几天前就遇到了这个问题(link )。 In 将通过简单的示例使这个简短。我有公司实体,其中包含多个实体员工和一个实体 CEO(从员工继承)。

完成我的数据模型后,我向这家公司添加了 5 名员工,我将 CEO 分配给了这家公司。在测试中,我打电话给 company.employees,预计会有 5 名员工,但结果与我预期的不一样,我也让 CEO 作为我的一名员工。

震惊于这个事件,我开始在apple doc上搜索解释,我看到两篇相关文章Fetching and Entity Inheritance说

如果您定义实体继承层次结构(请参阅“实体 继承”),当您将超实体指定为 获取请求,请求返回所有匹配的实例 超实体和子实体。

和Relationship Fundamentals说

关系指定实体或父实体 目的地的对象。这可以与在 来源(自反关系)。关系不一定是 同质。如果 Employee 实体有两个子实体,比如 Manager 和 Flunky,那么给定部门的员工可能由 员工(假设员工不是抽象实体)、经理、 Flunkies,或其任意组合。

这种行为正常吗?如果是,我可以安心地回来重新设计我的问题 (here)。如果有人能指出我记录在哪里更详细地解释了这种情况,那就太好了。

谢谢

更新主题并添加重现步骤 现在我在想这可能是某种 SDK 错误。这是我的复制步骤 制作3个实体

Family 
- int generation
- parents as to-may relation to Parent and family as inverse
- child as to-one relation to Child and family as inverse
Parent
- String name
- family to-one relation to Family
Child : Parent

这是我的代码

Family *fam;

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Family" inManagedObjectContext:self.managedObjectContext];

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entity];

NSArray *meters = [self.managedObjectContext executeFetchRequest:fetchRequest error:nil];

if ([meters count] > 0) 
    NSLog(@"found");
    fam = [meters lastObject];
    fam.generation = [NSNumber numberWithInt:[fam.generation intValue] + 1];
 else 
    NSLog(@"new");
    fam = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:self.managedObjectContext];
    fam.generation = [NSNumber numberWithInt:1];
    [self saveContext];
;
NSLog(@"There are %d paren", [fam.parents count]);
for (Parent *p in fam.parents) 
    NSLog(@"name : %@", p.name);

Child *child;
if (!fam.child) 
    child = [NSEntityDescription insertNewObjectForEntityForName:
             [[NSEntityDescription entityForName:@"Child" inManagedObjectContext:self.managedObjectContext] name]
                                          inManagedObjectContext:self.managedObjectContext];
    fam.child = child;

fam.child.name = [NSString stringWithFormat:@"child number %d", [fam.generation intValue]];
NSLog(@"There are %d parent after adding one child", [fam.parents count]);

Parent *parent = [NSEntityDescription insertNewObjectForEntityForName:
                  [[NSEntityDescription entityForName:@"Parent" inManagedObjectContext:self.managedObjectContext] name]
                                               inManagedObjectContext:self.managedObjectContext];
parent.name = [NSString stringWithFormat:@"parent number %d", [fam.generation intValue]];
[fam addParentsObject:parent];

NSLog(@"There are  %d parent after add parent", [fam.parents count]);
for (Parent *p in fam.parents) 
    NSLog(@"name : %@", p.name);


[self saveContext];

简而言之,我创建了一个家庭并将一个孩子和一个父母添加到这个家庭并打印出一些输出 在第一次运行中我得到了这个结果

2011-08-27 19:06:28.271 child[2015:207] new
2011-08-27 19:06:28.276 child[2015:207] There are 0 paren
2011-08-27 19:06:28.278 child[2015:207] There are 0 parent after adding one child
2011-08-27 19:06:28.279 child[2015:207] There are  1 parent after add parent
2011-08-27 19:06:28.280 child[2015:207] name : parent number 1

这是我的预期,然后我再次重新运行应用程序,这就是奇怪的事情发生

2011-08-27 19:08:12.383 child[2035:207] found
2011-08-27 19:08:12.386 child[2035:207] There are 2 paren
2011-08-27 19:08:12.387 child[2035:207] name : parent number 1
2011-08-27 19:08:12.388 child[2035:207] name : child number 1
2011-08-27 19:08:12.389 child[2035:207] There are 2 parent after adding one child
2011-08-27 19:08:12.390 child[2035:207] There are  3 parent after add parent
2011-08-27 19:08:12.390 child[2035:207] name : parent number 1
2011-08-27 19:08:12.391 child[2035:207] name : parent number 2
2011-08-27 19:08:12.391 child[2035:207] name : child number 2

子实体无缘无故包含在 fam.parents 属性中。

【问题讨论】:

对否决票有何评论?所以我下次可以改进我的问题。 【参考方案1】:

我不认为你引用的第一件事是你的问题。引用 company.employees 不是获取请求。

我怀疑这可能与反向关系有关。您是否在 Employee 上有一个关系公司,它是 Company.employees 的倒数?

那么当你将 CEO 分配到这样的公司时:

ceo.company = company;

然后,Core Data 在幕后说,ceo 是一名员工。当您将公司分配给员工时,请分配反向关系。将员工分配给公司的员工关系。它会自动生成以下代码的效果:

[company addEmployeesObject:ceo];

在我看来,逆向关系在 Core Data 中很烦人。很多时候你的代码不需要它们,但它们几乎都是 Core Data 内部工作所必需的。让我知道这是否是您的问题,我或许可以提出解决方法。

编辑:

您的父子示例第二次运行时的行为是我所期望的。

你分配

fam.child = child

Family.child 的反比关系是 Child.family,所以 Core Data 生成赋值

child.family = fam

子继承自父。 Parent.family的逆关系是Family.parent,所以Child.family的逆关系也是Family.parent。因此 Core Data 生成插入

[fam addParentsObject:child]

我没想到的是第一次运行的结果。如果将子对象添加到父对象,则应将其添加到托管对象上下文中,并且应立即可见。

也许您可以称其为错误,但无论如何,错误行为实际上是您想要的。您不想要的是第二次运行时发生的事情,这实际上是“正确”的行为。实际上,该行为实际上是未定义的,因为您构建了一个不一致的数据模型。你说的很有效

A.b的倒数是B.a

B.a 的倒数是 A.c

倒数并不是真正的倒数。我想你会在构建时发现一个警告。

好的,那么如何解决你原来的问题呢?

我的第一个建议是不要让 CEO 从 Employee 继承。但如果你有你想要这样做的理由,那么这里就是如何让它发挥作用。

Core Data 要求您定义逆数,并且逆数必须遵循 Core Data 的规则。如果您不想遵循 Core Data 的规则,则根据 Core Data 的规则定义逆,但不要使用它们。所以像这样定义你的数据模型:

Company
  employees: (to-many) Employee - inverse isEmployeeOf
  ceo: (to-one) CEO - inverse isCEOOf
  // unused
  people: (to-many) Employee - inverse company

Employee
  company: (to-one) Company - inverse people
  // unused
  isEmployeeOf: (to-one) Company - inverse employees

CEO : Employee
  // unused
  isCEOOf: (to-one) Company - inverse ceo

现在创建一个公司 myCompany,其中包含一名员工 mrEmployee 和一名 CEO mrCEO。您可能需要手动设置更多内容,因为您使用的属性没有定义逆数。

[myCompany addEmployeesObject:mrEmployee];
mrEmployee.company = myCompany; // not automatic, because not official inverse
myCompany.ceo = mrCEO;
mrCEO.company = myCompany;

然后它们将具有以下关系:

myCompany
  employees - mrEmployee
  ceo - mrCEO
  people - mrEmployee, mrCEO

mrEmployee
  company - myCompany
  isEmployeeOf - myCompany

mrCEO
  company - myCompany
  isEmployeeOf - myCompany
  isCEOOf - myCompany

【讨论】:

是的,我从 Employee 到 Company 有反比关系,并将 CEO 分配给像这样的公司 company.ceo = ceo 并添加员工 [company addEmployeesObject:otherEmployee]

以上是关于iOS SDK 上的错误或我对继承实体关系的误解?的主要内容,如果未能解决你的问题,请参考以下文章

ios 上的 AWSS3TransferUtilityErrorDomain 代码=2

抽象实体上的核心数据关系

这是 Files.lines() 中的错误,还是我对并行流有误解?

IOS 应用程序上的 Facebook SDK 错误

核心数据中的父实体和关系

navigationBar 和 MPMoviePlayerController 的极其奇怪的行为。 iOS中的错误或我的错误?