Должно ли каждое отношение данных к Core Data иметь обратное?

Скажем, у меня есть два класса Entity: SocialApp и SocialAppType

В SocialApp у меня есть один атрибут: appURL и одно отношение: type.

В SocialAppType у меня есть три атрибута: baseURL, name и favicon.

Назначение отношения SocialApp type - это одна запись в SocialAppType.

В качестве примера для нескольких учетных записей Flickr было бы количество записей SocialApp, каждая запись содержала бы ссылку на учетную запись человека. Для типа "Flickr" будет одна запись SocialAppType, на которую указывают все записи SocialApp.

Когда я создаю приложение с этой схемой, я получаю предупреждение о том, что между SocialAppType и SocialApp нет обратной зависимости.

 /Users/username/Developer/objc/TestApp/TestApp.xcdatamodel:SocialApp.type: warning: SocialApp.type -- relationship does not have an inverse

Нужен ли мне обратный и почему?

Ответ 1

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

Обратные отношения не просто сделать вещи более аккуратными, это на самом деле используется Core Data для хранения данных Целостность.

- Cocoa Dev Central

Вы должны обычно моделировать отношения в обоих направлениях, и указать обратные отношения соответственно. Базовые данные используют это информация для обеспечения согласованности графа объекта, если изменение сделано (см. "Управление отношениями" и целостность графов объектов "). Для обсуждение некоторых причин, по которым Вы можете не моделировать отношения в обоих направлениях, и некоторые из проблем, которые могут возникнуть если нет, см. "Однонаправленный Отношения.

- Руководство по программированию основных данных

Ответ 2

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

Предположим, вы смоделировали его следующим образом: enter image description here

Обратите внимание, что у вас есть отношение к одному, называемое type ", от SocialApp до SocialAppType. Отношение не необязательно и имеет правило " deny" delete.

Теперь рассмотрим следующее:

SocialApp *socialApp;
SocialAppType *appType;
// assume entity instances correctly instantiated

[socialApp setSocialAppType:appType];
[managedObjectContext deleteObject:appType];
BOOL saved = [managedObjectContext save:&error];

Мы ожидаем, что этот контекст сохранится, поскольку мы установили правило удаления как Deny, а отношение не является необязательным.

Но здесь сохранение выполнено успешно.

Причина в том, что мы не установили обратную связь. Из-за этого экземпляр socialApp не становится помеченным как измененный при удалении appType. Таким образом, для socialApp не требуется проверки, прежде чем сохранять (он не требует проверки, поскольку никаких изменений не произошло). Но на самом деле произошло изменение. Но это не отражается.

Если мы вспомним appType

SocialAppType *appType = [socialApp socialAppType];

appType - нуль.

Странно, не так ли? Мы получаем nil для необязательного атрибута?

Итак, у вас нет проблем, если вы настроили обратную связь. В противном случае вы должны выполнить проверку силы, написав код следующим образом.

SocialApp *socialApp;
SocialAppType *appType;
// assume entity instances correctly instantiated

[socialApp setSocialAppType:appType];
[managedObjectContext deleteObject:appType];

[socialApp setValue:nil forKey:@"socialAppType"]
BOOL saved = [managedObjectContext save:&error];

Ответ 3

Я перефразирую окончательный ответ, который я нашел в More iPhone 3 Development от Дейва Марка и Джеффа ЛеМарче.

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

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

Но , если у вас нет конкретной причины, не моделируйте обратный. Это помогает Core Data обеспечивать целостность данных. Если вы столкнулись с проблемами производительности, относительно легко удалить обратную связь позже.

Ответ 4

Лучший вопрос: "есть ли причина не иметь обратного"? Основные данные - это действительно структура управления графами объектов, а не система персистентности. Другими словами, его задача - управлять отношениями между объектами в графе объектов. Обратные отношения делают это намного проще. По этой причине Core Data ожидает обратные отношения и написана для этого случая использования. Без них вам придется самостоятельно управлять контурами объектов. В частности, к-многим без обратной связи, очень вероятно, будут повреждены Core Data, если вы работаете очень трудно держать вещи работать. Стоимость с точки зрения размера диска для обратных отношений действительно незначительна по сравнению с выгодой, которую она вам приносит.

Ответ 5

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

Например, книга содержит много страниц, а страница - в одной книге. Это двусторонние отношения "много-к-одному". Удаление страницы просто аннулирует связь, в то время как удаление книги также удалит страницу.

Однако вы также можете отслеживать текущую страницу, читаемую для каждой книги. Это можно сделать с помощью свойства currentPage на странице, но тогда вам понадобится другая логика, чтобы в любой момент пометить как одну страницу в книге как текущую страницу. Вместо этого, если отношение currentPage от книги к одной странице будет гарантировать, что всегда будет отображаться только одна текущая страница, и, кроме того, эта страница может быть легко доступна с ссылкой на книгу с помощью просто book.currentPage.

Graphical presentation of core data relationship between books and pages

Каковы были бы взаимные отношения в этом случае? Что-то в значительной степени бессмысленно. "myBook" или подобное может быть добавлено обратно в другом направлении, но в нем содержится только информация, уже содержащаяся в отношении "книги" для страницы, и поэтому создает свои собственные риски. Возможно, в будущем изменится способ использования одного из этих отношений, что приведет к изменениям в вашей конфигурации основных данных. Если page.myBook использовался в некоторых местах, где page.book должен был использоваться в коде, могут возникнуть проблемы. Другой способ упредить это можно было бы также не подвергать myBook в подклассе NSManagedObject, который используется для доступа к странице. Однако можно утверждать, что проще не моделировать обратное в первую очередь.

В приведенном примере правило удаления для отношения currentPage должно быть установлено на "No Action" или "Cascade", так как нет взаимного отношения к "Nullify". (Каскад подразумевает, что вы вырываете каждую страницу из книги, когда читаете ее, но это может быть правдой, если вы особенно холодны и нуждаетесь в топливе.)

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

Ответ 6

Пока документы не требуют обратного, я просто решил сценарий, который фактически привел к "потере данных", не имея обратного. У меня есть объект отчета, который имеет отношение "многие" к отчетным объектам. Без обратной зависимости любые изменения отношения ко многим были потеряны после перезапуска. После проверки отладки основных данных было очевидно, что, хотя я сохранял объект отчета, обновления графиков объектов (отношений) никогда не выполнялись. Я добавил инверсию, хотя я ее не использую, и вуаля, она работает. Поэтому он может не сказать, что это необходимо, но отношения без инверсий могут иметь странные побочные эффекты.

Ответ 7

Инверсы также используются для Object Integrity (по другим причинам см. другие ответы):

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

От: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreData/HowManagedObjectsarerelated.html#//apple_ref/doc/uid/TP40001075-CH17-SW1

Приведенная ссылка дает вам идеи, почему вы должны иметь набор inverse. Без этого вы можете потерять данные/целостность. Кроме того, вероятность того, что вы получите доступ к объекту, который является nil, более вероятна.

Ответ 8

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