Копирование всего графа объекта - копирование отношения - PullRequest
1 голос
/ 14 февраля 2010

У меня есть модель с двумя объектами: RealEstate и Container

Объект контейнеров уже сохранен в постоянном хранилище со следующей иерархией:

Container 1
    Container 2
    Container 3
Container 4
    Container 5
        Container 6

Каждый контейнер имеет владельца RealEstate (в данной иерархии realEstate всегда одинаково) Теперь я хотел бы создать копию этой иерархии, изменяя для каждого контейнера владельца realEstate. После некоторых испытаний мне кажется, что это не тривиальная проблема.

Это упрощенная схема модели:

RealEstate (entity)
-------------------
name (string attribute)
containers (relation)

Container (entity)
------------------
level (int attribute)
name (string attribute)
parent (self relation to another container)
subcontainers (relation - set of containers)
realEstate (relation)

В основном каждый контейнер имеет отношение подконтейнеров к себе и родительское отношение, например, Контейнер 1 не имеет родителя, но подконтейнеры = [контейнер 2, контейнер 3] и т. Д. *

У меня есть 2 вопроса:

  • если я хочу скопировать один атрибут (NSNumber), я должен скопировать атрибут перед тем, как назначить его скопированному контейнеру с чем-то вроде [newContainer setLevel: [[уровень контейнера] copy]], потому что NSNumber на самом деле является указателем, или это нормально назначить [newContainer setLevel: [уровень контейнера]] ??
  • как скопировать отношение ?? Я не могу просто скопировать субконтейнеры с помощью [newContainer setSubcontainers: [контейнерные субконтейнеры]] !!

Вот что я делаю:

- (void)copyContainersFromRealEstate:(RealEstate *)sourceRealEstate toRealEstate:(RealEstate *)destinationRealEstate {
    // read all RealEstate Containers to copy
 NSFetchRequest *request = [[NSFetchRequest alloc] init];
 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"realEstate == %@", sourceRealEstate];
 [request setPredicate:predicate];
 [request setEntity: [ NSEntityDescription entityForName:@"Container"
                 inManagedObjectContext:destinationRealEstate.managedObjectContext] ];

 NSError *error;
 NSArray *results = [destinationRealEstate.managedObjectContext executeFetchRequest:request 
                          error:&error];

 if (results == nil) {
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
      abort();
 }
 [request release];

    // *******************************************************
 // copy each caontainer changing the real estate
 Container *newContainer;
 for (Container *container in results) {
      newContainer = (Container *)[NSEntityDescription insertNewObjectForEntityForName:@"Container" 
                 inManagedObjectContext:destinationRealEstate.managedObjectContext];

      [newContainer setRealEstate:destinationRealEstate];
      [newContainer setLevel:[container level]];
      [newContainer setSubcontainers:[container subcontainers]];  // WRONG
      [newContainer setName:[container name]];
      [newContainer setParent:[container parent]];  // WRONG
 }
    // *******************************************************

}

Любая помощь будет оценена. Спасибо

Ответы [ 2 ]

1 голос
/ 14 февраля 2010

если я хочу скопировать один атрибут (NSNumber), следует ли мне скопировать атрибут перед назначением его скопированному контейнеру с чем-то вроде [newContainer setLevel: [[уровень контейнера] copy]], потому что NSNumber на самом деле является указателем хорошо назначить [newContainer setLevel: [уровень контейнера]] ??

Установите значение для нового объекта, он будет обрабатывать его, даже если он является указателем, потому что Core Data будет записывать значение в базу данных, поэтому он будет преобразовывать его в примитив в некоторый момент и «разбивать», что отношение указателя, которое вас беспокоит.

как скопировать отношение ?? Я не могу просто скопировать субконтейнеры с помощью [newContainer setSubcontainers: [контейнерные субконтейнеры]] !!

Просто установите объекты, и Core Data сделает правильные вещи и правильно построит новые отношения. Когда вы передаете NSSet новому родительскому объекту, Core Data будет перебирать объекты в наборе и создавать новые связи отношений для каждого из них с новым родительским объектом.

0 голосов
/ 16 февраля 2010

Спасибо за ваш ответ. Извините, если напишите как новый ответ, но это единственный способ опубликовать скриншот.

Просто установите объекты, и Core Data сделает правильные вещи и правильно построит новые отношения. Когда вы передаете NSSet новому родительскому объекту, Core Data будет выполнять итерацию по объектам в наборе и создавать новые связи отношений для каждого из них с новым родительским объектом.

Я понимаю, что coredata создаст новые отношения отношений с новым родительским объектом и автоматически внесет необходимые изменения, особенно если отношение моделируется в обоих направлениях, но в моем случае что-то идет не так, возможно, из-за того, как я проектировал свои отношения. Просматривая мой код, я вижу, что [newContainer setParent: [container parent]]; не требуется, поскольку «parent» и «subcontainers» являются обратными отношениями, поэтому установка «subcontainers» автоматически установит «parent». Но даже с этим изменением что-то не так.

Чтобы упростить задачу, я только что сделал этот тест:

  • допустим, я просто хочу скопировать поддерево, а не целое дерево, например, Контейнер 5 с его дочерним Контейнером 6 (см. Иерархию из моего первого ответа)
  • сначала проверяет, что отношения правильны из источника: если я распечатываю sourceRealEstate Container 5, я вижу: Container5.parent = Container4, Container5.subcontainers = [Container 6] . Таким образом, кажется, что все в порядке в источнике копирования
  • чем начать процедуру копирования ... после этого я пытаюсь таким же способом распечатать скопированный объект и вижу: Container5.parent = nil (WRONG), Container5.subcontainers = [Container 6] ( ПРАВЫЙ) . Затем я проверяю исходный контейнер и вижу: * Container 5.parent = Container 4 (RIGHT), Container5.subcontainer = empty (WRONG)

Выводы: субконтейнеры перемещены и не скопированы

Это моя модель более подробно:

http://www.freeimagehosting.net/uploads/9aae9b9ac8.png

Контейнер. Родительские отношения:
http://www.freeimagehosting.net/uploads/7f5c6592ef.png

Отношение Container.subcontainers:
http://www.freeimagehosting.net/uploads/bff3e1abe8.png

...