47

我使用 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 OnethroughBook N与一个Owner( "alexpreynolds, 123456") 相关联。

我将其解析为一个Owner实例和一个NSMutableSet由实例组成的Book实例。

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

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

这是发生的事情:

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

我有一些例程可以挑选出这个唯一的Owner托管对象(我已经在我的主托管对象上下文中拥有)和在主 MOC 中找不到Book唯一对象。

由此,我Book在辅助 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 中预先存在的实体相关联?

4

6 回答 6

72

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

例如:

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已经保存的情况下才有可能。托管对象上下文将在持久存储中查找对象,因此必须先保存它。

于 2009-10-12T14:35:55.297 回答
11

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

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

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

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

我希望这有帮助 :)

于 2013-02-25T18:46:14.707 回答
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
})

希望对你有帮助!

于 2016-04-18T11:23:25.767 回答
2

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

于 2009-10-12T13:38:53.867 回答
1
book *book = [mainContext ........]   //Get book from default context

NSManagedObjectID *objectId = [book objectID];

Book *tmpBook = [tmpContext objectWithID:objectId]; //Now book has the legal relationship
于 2016-04-18T07:25:28.083 回答
1

迅捷版...

context.insert(objectFromOtherContext)
于 2018-06-01T01:35:43.253 回答