如何强制UNIDIRECTIONAL与
核心数据存在问题,当多对一关系没有反转时。 对相关属性所做的更改不会持续。 这是我们很多人面临的问题,因为它可以通过Google搜索找到。
这是为了询问你们中的一些人是否找到了一种诀窍/解决方法来实现持久性,除了明显的答案或添加了反向关系之外。
背景 :
例
在员工/部门典型范例中,如果拥有数量庞大的员工能够属于多个部门,则需要从员工到部门的多对多关系。 你不想逆,因为每个雇员被链接到一个部门的时候,一个(非常)大的NSSet必须加载,更新和保存。 此外,如果部门实体从未被删除,图表完整性很容易维护。
请不要回复这是核心数据的一项功能,而且这种反向关系是强制性的。 这并非如此,更像是一个bug而不是一个功能。 发布错误报告并不能解决当前部署系统的问题。
编辑:加入实体解决方案此编辑旨在让丹·谢利的答案建议更多的提示和讨论。
首先,为了回复你的第一个问题,我并不是想要多对多,而是一个真正的单向多对多。 您链接的页面与您引用的页面相比稍低一点:
单向关系
在两个方向上建立关系并非严格必要。 在某些情况下,它可能不是有用的,例如,当一对多关系可能有大量的目标对象时,并且很少可能会遍历关系(您可能希望确保您不会不必要地在关系目的地处的大量对象)。 但是,如果不在两个方向上建立关系模型,都会对您承担很多责任,以确保对象图的一致性,进行更改跟踪以及撤消管理。
这表示,如果没有解决方案强制核心数据自动生成和更新,那么您提出的添加联合实体的解决方案是一种方法。
国际海事组织,并为我的使用情况下,联合实体甚至不需要与部门的关系。 这一对一是无用的,并且可以由保持相关部门信息的连接实体的属性取代,例如其对象ID或其他索引属性以达到它。
  即: 
  DepartmentEmployee: 
  属性:Dept_ix(整数) 
  关系:员工(一对一,无效) 
  这是一个很好的问题。 
  但首先是: 
  它在文档中明确指出: 
“重要的是:你必须在两个方向上定义多对多的关系 - 也就是说,你必须指定两个关系,每个关系都是另一个关系的反向关系。你不能只在一个方向上定义一个多对多的关系,并尝试把它当作多对多的使用,如果你这样做,你最终会遇到参照完整性问题。“
  从来没有,让我们描述这个问题(产生的数据库) 
  定义多对多关系时,生成的数据库不会添加额外的表来映射关系。 
  它只在对多关系一端的实体上设置一个属性,等于引用它的最后一个项目。 
例:
  模型: 
  实体:部门 
  关系:无 
  属性:name(字符串) 
  实体:员工 
  关系:部门(多对多,无行动) 
  属性:名称 
  结果数据库: 
  ZDEPARTMENT: 
  Z_PK 
  Z_ENT 
  Z_OPT 
  Z2DEPARTMENTS(int) 
  ZNAME 
  ZEMPLOYEE: 
  Z_PK 
  Z_ENT 
  Z_OPT 
  ZNAME 
  这种结构显然会导致数据不一致。 
  解决方案将包含一个实体: DepartmentEmployee在两个方向上建模多对多关系,但其中一个将是单向的(Department  - > DepartmentEmployee): 
  DepartmentEmployee: 
  关系:部门(一对一,不采取行动),员工(一对一,无效) 
并且在删除部门对象时必须维护表格。
希望这有些道理:)
  首先回复你的评论: 
  国际海事组织,并为我的使用情况下,联合实体甚至不需要与部门的关系。  这一对一是无用的,并且可以由保持相关部门信息的连接实体的属性取代,例如其对象ID或其他索引属性以达到它。 
  这正是部门财产在联合关系中所做的。 
  如果您要查看生成的SQLite结构,您将看到Employee实体和Department实体之间的附加映射表,仅保存它们的int64 ID。 
  现在,给出的例子是: 
例
  在员工/部门典型范例中,如果拥有数量庞大的员工能够属于多个部门,则需要从员工到部门的多对多关系。  您不需要反过来,因为每次员工链接到部门时,必须加载,更新和保存(非常)大的NSSet。  此外,如果部门实体从未被删除,图表完整性很容易维护。  一个简单的一对多的关系,没有反转,可以很容易地实现。 
  您可以将它视为关系“多边”一侧的对象上的另一个属性。 
  这个例子请求了一种一对多的关系: 
  员工 -  >>部门(员工可能属于多个部门) 
  反过来是: 
  部门 - >员工 
  由于我们不能实现多对多的关系而没有相反的关系,所以我们必须实现关系的一方,以确保我们遵守框架的实施。 
  重新迭代: 
  通过文档我们知道,如果没有定义反向关系,不会存在多对多关系。 
  ==> 
  由于我们喜欢在没有反转的情况下对关系进行建模,因此我们只会将它建模为耦合的to-one部分(将它建模为to-many会违反框架所承诺的持久性) 
  把它看作在文件夹中定义文件(一个文件可能不属于多个文件夹)或父子关系是有用的。 
  ==> 
  我们必须将关系定义为: 
  部门 - >员工(这是没有什么道理的,因为只有一个员工的部门实际上不是一个部门) 
  从另一个天使来看它(负面证据): 
  假设我们想要违背框架并且定义一个多对多的关系而不是相反的。 
  ==> 
  这意味着我们只会在一个方向上实施,留下......多对多的关系或......多对多的关系 
  ==> 
  这同样是不同的(从entity1到entity2的多对多关系) 
  ==> 
  现在,如果我们有一对多的关系,而且我们选择不实现它的逆,我们可以选择实现多对多的部分?  不 , 我们不能 ,这只会成为多对多关系的一半==> 
  我们必须实施它的一部分。 
  为了更有意义,我将展示更合乎逻辑的: 
  部门 -  >>员工因此,我们对此一对多关系的实施将是: 
  系< - 员工 
  这将导致以下SQLite数据库结构: 
  ZDEPARTMENT: 
  Z_PK 
  Z_ENT 
  Z_OPT 
  ZNAME 
  ZEMPLOYEE: 
  Z_PK 
  Z_ENT 
  Z_OPT 
  ZDEPARTMENT(int) 
  ZNAME 
  我们现在可以在Department上定义一个抓取的属性来获取属于它的所有员工: 
  employees谓词: department == $FETCH_SOURCE 
  您可以在Department的prepareForDeletion方法中强制执行此关系(未测试): 
  (您将首先在Department上设置userInfo字典以保存强制类型) 
  (我给读者留下了“拒绝”规则的实施:D) 
- (void) prepareForDeletion
{
    [super prepareForDeletion];
    NSEntityDescription* entity = [self entity];
    NSDictionary* dict = [entity userInfo] ;
    if ([dict count]) {
        [dict enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSString* value, BOOL *stop) {
            NSArray* arr = [self valueForKey:key];
            if( [value isEqualToString:@"cascade"]) {
                for (NSManagedObject* obj in arr) {
                    [[self managedObjectContext] deleteObject:obj];
                }
            } else if ( [value isEqualToString:@"nullify"] ) {
                NSArray* arr = [self valueForKey:key];
                for (NSManagedObject* obj in arr) {
                    [obj setValue:nil forKey:@"department"];
                }
            }
        }];
    }
}
正如我所看到的,这是关于反向关系所能做的。 如果你仍然相信你需要多对多的关系,请参考我的其他答案。
  问候, 
  担。 
您是否考虑彻底废除关系并以编程方式管理员工的外键?
  如果您有一个用户界面来设置现有部门列表中的属性(选择列表等),您可以简单地从该列表中获取主键,并将其指定为员工的departmentID属性。 
  然后,您应该能够在Employee对象上实现validateDepartmentID:error方法,该方法检查给定的departmentID是否有效(即位于部门的提取列表中)和/或不为null,以便保持Employee和部。 
  在提取部门中的员工列表时,您可以使用提取的属性,也可以将实例方法添加到部门,该部门返回包含部门员工列表的NSFetchedResultsController实例。 
  您唯一需要做的其他事情是在您的Department类中注入一些删除逻辑(可能在-prepareForDeletion )以更新任何受影响的子记录上的departmentID 。  这取决于你的业务逻辑。 
  属性验证的Apple文档覆盖了-prepareForDeletion和-validateValue:forKey:error如果您不熟悉它们。 
