setIncludeSubentities: в NSFetchRequest не работает для сущностей через несколько постоянных хранилищ - PullRequest
1 голос
/ 04 мая 2010

Уровень техники, который не совсем решает эту проблему: Сообщение об ошибке миграции основных данных «Модель не содержит конфигурацию« XYZ ».»

Я сузил это до конкретной проблемы. Это займет минуту, чтобы настроить, хотя; пожалуйста, потерпите меня.

Суть проблемы в том, что persistentStoreCoordinator (по-видимому) не может сохранить часть графа объектов, где управляемый объект помечается как подчиненный объект другого, когда они хранятся в разных файлах. Здесь идет ...

1) У меня есть 2 файла xcdatamodel, каждый из которых содержит одну сущность. Во время выполнения, когда создается модель управляемого объекта, я вручную определяю один объект как подраздел другого, используя setSubentities :. Это связано с тем, что определение подразделов в нескольких файлах в редакторе пока не поддерживается. Затем я возвращаю полную модель с modelByMergingModels.

//Works! 
[mainEntity setSubentities:canvasEntities];
NSLog(@"confirm %@ is super for %@", [[[canvasEntities lastObject] superentity] name], [[canvasEntities lastObject] name]);
//Output: "confirm Note is super for Browser"

2) Я изменил метод persistentStoreCoordinator, чтобы он устанавливал разные хранилища для каждой сущности. Технически он использует конфигурации, и для каждого объекта определена одна и только одна конфигурация.

//Also works!
for ( NSString *configName in [[HACanvasPluginManager shared].registeredCanvasTypes valueForKey:@"viewControllerClassName"] ) {
storeUrl = [NSURL fileURLWithPath:[[self applicationDocumentsDirectory] stringByAppendingPathComponent:[configName stringByAppendingPathExtension:@"sqlite"]]];
//NSLog(@"entities for configuration '%@': %@", configName, [[[self managedObjectModel] entitiesForConfiguration:configName] valueForKey:@"name"]);
//Output: "entities for configuration 'HATextCanvasController': (Note)"
//Output: "entities for configuration 'HAWebCanvasController': (Browser)"
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:configName URL:storeUrl options:options error:&error])
//etc

3) У меня есть набор fetchRequest для родительской сущности, с setIncludeSubentities: и setActedStores: просто чтобы быть уверенными, что мы покрываем оба 1) и 2). При вставке объектов любого объекта они оба добавляются в контекст, и они оба выбираются fetchedResultsController и отображаются в табличном представлении, как и ожидалось.

// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entity];
[fetchRequest setIncludesSubentities:YES]; //NECESSARY to fetch all canvas types
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setFetchBatchSize:20]; // Set the batch size to a suitable number.
[fetchRequest setAffectedStores:[[managedObjectContext persistentStoreCoordinator] persistentStores]];
[fetchRequest setReturnsObjectsAsFaults:NO];

Вот где он начинает плохо себя вести: после закрытия и перезапуска приложения выбирается ТОЛЬКО РОДИТЕЛЬСКИЙ СУЩНОСТЬ.

Если я изменяю сущность запроса, используя setEntity: на сущность для «Заметки», все заметки извлекаются. Если я изменю его на сущность для «Браузер», все браузеры будут загружены. Позвольте мне повторить, что во время выполнения, когда объект впервые вставляется в контекст, он появится в списке. Только после сохранения и повторного запуска запрос на выборку не может пройти через иерархию.

Поэтому я могу только сделать вывод, что проблема заключается в хранении наследства. Давайте вспомним, почему:

Это оставляет только одного виновника (на мой взгляд): наследование, которое я устанавливаю с помощью setSubentities: действует только для объектов, создаваемых во время сеанса.

Либо объекты / сущности сохраняются без информации о наследовании, либо наследование сущностей, как определено программно, применяется только к новым экземплярам, ​​или к обоим. Любой из них неприемлем. Либо это ошибка, либо я слишком далеко от курса.

Я занимался этим в разные стороны в течение двух дней; Любое понимание очень ценится. Текущий обходной путь - только использование одного магазина - работает полностью, за исключением того, что он не будет ориентирован на будущее в случае, если я удалю одну из моделей из приложения и т. Д. Это также ошеломляет разум, потому что я не понимаю, почему вы будет иметь всю эту инфраструктуру для хранения в нескольких хранилищах и для установки уязвимых хранилищ в запросах на выборку, если она по определению ядра (из setSubentities :) не работает.

Ответы [ 2 ]

4 голосов
/ 04 мая 2010

Ответ, к сожалению, прост. Субтитры между физически разными файлами и / или моделями не поддерживаются. В базовой структуре данных Core Data возьмет все дочерние объекты и сведет их в одну таблицу. Так что если у вас есть Parent, ChildA, ChildB и ChildC, каждый из которых имеет 4 атрибута, то в итоге вы получите одну таблицу с 16 столбцами.

Вот почему суб-сущности не поддерживаются так, как вы пытаетесь. Каждая модель представляет собой отдельный бункер и может в большинстве случаев иметь слабые ссылки на объекты в других моделях.

Обновление

Это проблема "не поддерживается дизайном", как я объяснил выше. То, что вы пытаетесь сделать, не поддерживается из-за того, как оно сохраняется в базовой структуре данных. Создание суб-сущностей - это не то, чем вы должны заниматься в первую очередь, потому что это выравнивает вашу модель данных.

Наследование сущностей не равнозначно наследованию объектов. Ваши объекты могут наследовать любым способом, в любой форме или форме, которую вы хотите. Наследование сущностей должно быть крайне редким и иметь за этим очень вескую причину.

Решение проблем родительских и дочерних отношений является одной из немногих причин использования наследования объектов.

Попытка избежать дублирования столбцов не веская причина.

Поскольку вы не можете установить отношения родитель / потомок между моделями (и у вас есть более одной модели, даже если они объединяются в один экземпляр из NSManagedObjectModel), это вряд ли является причиной выполнить наследование сущностей в разных моделях, которые невозможно решить с помощью аналогичного решения.

0 голосов
/ 14 июля 2011

@ SG

Вы спрашиваете:

Почему существуют все эти ловушки для чтения в нескольких моделях и сохранения в нескольких постоянных хранилищах ...

Вы можете иметь несколько моделей и сохранять их в разных постоянных хранилищах, потому что вы хотите работать с разными частями вашей xcdatamodel, например, редактирование атрибутов EntityA, влияющих на отношения с EntityB, при переупорядочивании огромного количества управляемых объектов EntityB.

Вы могли бы также улучшить потоковую передачу ввода-вывода в другом потоке при чтении в новых объектах, после выполнения этой работы вы могли бы «объединить» их с существующими данными вашей модели.

...