非法尝试在不同上下文中的对象之间建立关系'xyz'

时间:2009-10-12 13:35:32

标签: iphone core-data nsfetchedresultscontroller

我使用Apple的CoreDataBooks示例应用程序作为在后台将数据提取到辅助托管对象上下文的基础,然后将该数据合并到主要托管对象上下文中。

我所引入的数据是Book实体,与Owner实体(称为“所有者”)具有一对一的关系。 Owner实体与Book(称为“图书”)有多对多的关系。

我的数据是以下格式的XML文档:

<Owner>
  <Name>alexpreynolds</Name>
  <ID>123456</ID>
</Owner>
<Books>
  <Book>Book One</Book>
  <Book>Book Two</Book>
  ...   
  <Book>Book N</Book>
</Books>

Book OneBook N与一个Owner"alexpreynolds, 123456")相关联。

我正在将此解析为Owner个实例和NSMutableSet实例组成的Book

当我第一次尝试保存时,它保存得很好,合并的数据显示在表格视图中。

然而,在第二次保存时,当XML内容包含新书时,它不起作用。

以下是发生的事情:

然后,我尝试加载一个XML文档,该文档包含一个尚未在主要托管对象上下文中的新Book。新Book使用的Owner与其他Book使用的Owner相同。

我有一些例程可以选择这个唯一的Book托管对象(我已在主要托管对象上下文中使用)和在中找不到 的唯一Book主要的MOC。

由此,我在辅助MOC中创建了一个新的owner对象,并将其“Owner”关系设置为指向我在主要MOC中找到的唯一*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Illegal attempt to establish a relationship 'owner' between objects in different contexts (source = <Book: 0x7803590> (entity: Book; id: 0x7802ae0 <x-coredata:/// Book/t527F06B2-3EB5-47CF-9A29-985B0D3758862> ; data: { creationDate = 2009-10-12 06:01:53 -0700; name = nil; nameInitial = nil; operations = ( ); owner = nil; type = 0; }) , destination = <Owner: 0x78020a0> (entity: Owner; id: 0x3a56f80 <x-coredata://043AF2F0-1AD0- 4078-A5E8-E9D7071D67D1/Owner/p1> ; data: { books = "<relationship fault: 0x7801bf0 'books'>"; displayName = alexpreynolds; ownerID = 123456; }))'

保存时,出现以下错误:

Book

如何在辅助MOC中创建新的Owner实体,以便我仍然可以将其与主要MOC中预先存在的{{1}}相关联?

6 个答案:

答案 0 :(得分:67)

您不能在不同的托管对象上下文中的对象之间建立关系。因此,解决这个问题的一种方法是将对象带入托管对象上下文。

例如:

NSManagedObject *book = // get a book in one MOC
NSManagedObject *owner = // get an owner in a different MOC
[[owner mutableSetValueForKey:@"books"] addObject:[owner.managedObjectContext objectWithID:[book objectID]]];

因此,您所做的实际上是将Book提取到owner的同一个托管对象上下文中。但请记住,只有在book已保存的情况下才可以这样做。托管对象上下文将在持久性存储中查找对象,因此必须先保存它。

答案 1 :(得分:9)

我有同样的问题,这句话帮我解决了错误。

  

您不能在不同托管的对象之间建立关系   对象上下文。因此,解决这个问题的一种方法是带来   对象进入托管对象上下文。

这是我的代码(我替换了变量以使其适合您):

// Have the owner object and get the managedObjectContext
Owner *owner = [[DataFunctions alloc] getCurrentOwner];
NSManagedObjectContext *context = [owner managedObjectContext]; 

// Create a book and use the manageObjectContext of owner
Book *book = [NSEntityDescription insertNewObjectForEntityForName:@"Book" inManagedObjectContext:context];
[newQuote setValue: "Book Title" forKey:@"title"];
[newQuote setOwner:owner];

我希望这会有所帮助:)

答案 2 :(得分:4)

在这里,您尝试在使用不同上下文获取/创建的两个对象之间建立关系。核心数据不会让您建立这样的关系。要实现这一点,您应该使用objectID获取第一个对象的上下文(您尝试与之建立关系)。现在,您应该能够在这两个对象之间建立关系。例如:

MagicalRecord.saveWithBlock({[unowned self] (localContext: NSManagedObjectContext!) in

    let user = User.MR_createEntityInContext(localContext)!
    .....
    .....
}) //here local context stores data on end of block itself

MagicalRecord.saveWithBlock({[unowned self] (localContext: NSManagedObjectContext!) in

    let address = Address.MR_createEntityInContext(localContext)!
    .....
    .....
    let user = localContext.objectWithID(self.user!.objectID) as! User
    user.address = address
})

希望这会对你有帮助!

答案 3 :(得分:1)

如错误所示,您不允许在一个Core Data对象中建立关系,该对象的值设置为另一个上下文中保存的另一个对象。解决这个问题的一种方法是等到保存新对象并将其合并回主要上下文之后,然后根据需要设置owner关系(因为两个对象现在都在同一个上下文中,所以没有问题)。

答案 4 :(得分:0)

book *book = [mainContext ........]   //Get book from default context

NSManagedObjectID *objectId = [book objectID];

Book *tmpBook = [tmpContext objectWithID:objectId]; //Now book has the legal relationship

答案 5 :(得分:0)

Swift版本......

context.insert(objectFromOtherContext)