Отношения и выбранные свойства
Существует много вещей, которые необходимо решить при создании отношения. Каков целевой объект? Действительно ли это к - один или к - многие? Действительно ли это является дополнительным? Если это к - многие, есть ли максимальные или минимальные числа объектов, которые могут быть в отношении? Когда исходный объект удален, что должно произойти? Можно предоставить ответы ко всем они в модели. Один из особенно интересных случаев является many-many отношением; существует два способа смоделировать их, и какой, который Вы выбираете, будет зависеть от семантики Вашей схемы.
При изменении графа объектов важно поддержать ссылочную целостность. Базовые Данные упрощают для Вас изменять отношения между управляемыми объектами, не вызывая ошибки ссылочной целостности. Большая часть этого поведения происходит из описаний отношения, указанных в модели управляемого объекта.
Базовые Данные не позволяют Вам создать отношения тот крест хранилища. Если необходимо создать отношение из объектов в одном хранилище к объектам в другом, необходимо рассмотреть использование выбранных свойств.
Определения отношения в модели
Создание отношения в модели управляемого объекта является прямым, но существует много аспектов отношения, которое необходимо указать должным образом. Наиболее очевидные функции являются именем отношения, целевой объект и кардинальность (он к - одно отношение, или к - многие отношение). Самые важные функции относительно целостности графа объектов, однако, являются обратной связью и удалить правилом. Законность графика затронута настройками для возможностей и для максимального и минимального количества.
Основные принципы отношения
Отношение указывает объект или родительский объект, объектов в месте назначения. Это может совпасть с объектом в источнике (рефлексивное отношение). Отношения не должны быть гомогенными. Если объект Сотрудника имеет два подобъекта, говорят менеджер и Лакей, то сотрудники данного отдела могут быть составлены из Сотрудников (предполагающий, что Сотрудник не является абстрактным объектом), менеджеры, Лакеи или любая комбинация этого.
Можно указать отношение, как являющееся к - один или к - многие. К - отношения представлены ссылкой на целевой объект. К - много отношений представлены непостоянными наборами (несмотря на то, что выбранные свойства представлены массивами). Неявно, “к - один” и “к - многие” обычно обращаются к «непосредственным» и «one-many» отношениям соответственно. Many-many отношение является тем, где отношение и его инверсия оба к - многие. Они представляют некоторые дополнительные соображения и обсуждены более подробно в Отношениях Many-Many.
Можно также поместить верхний и нижние пределы на числе объектов в месте назначения к - многие отношение. Нижний предел не должен быть нулем. Вы можете, если Вы хотите, указывают, что численность персонала в отделе должна находиться между 3 и 40. Вы также указываете отношение или как дополнительное или как не дополнительные. Если отношение не является дополнительным, то, чтобы быть допустимыми, должен быть объект или объекты в месте назначения отношения.
Кардинальность и возможности являются ортогональными свойствами отношения. Можно указать, что отношение является дополнительным даже при указании верхних и/или нижних границ. Это означает, что не должно быть никаких объектов в месте назначения, но если существует тогда число объектов, должен лечь в указанных границах.
Важно отметить, что просто определение отношения не заставляет целевой объект создаваться, когда создается новый исходный объект. В этом отношении определение отношения сродни объявлению переменной экземпляра в стандартном классе Objective C. Рассмотрите следующий пример.
@interface Widget : NSObject |
{ |
Sprocket *sprocket; |
} |
При создании экземпляра Виджета экземпляр Звездочки не создается, если Вы не пишете код, чтобы заставить его происходить (например, путем переопределения init
метод). Точно так же при определении объекта Адреса и обязательного к - одно отношение от Сотрудника для Обращения, затем просто создавая экземпляр Сотрудника не создает новый экземпляр Адреса. Аналогично, если Вы определяете обязательное к - многие отношение от Сотрудника для Обращения с минимальным количеством 1
, тогда просто создание экземпляра Сотрудника не создает новый экземпляр Адреса.
Обратные связи
Большинство отношений является по сути реверсивным. Если Отдел имеет к - многие отношение Сотрудникам, работающим в Отделе, существует обратная связь от Сотрудника к Отделу. Главное исключение является выбранным свойством, представляющим слабое одностороннее отношение — нет никакого отношения от места назначения к источнику (см. Выбранные Свойства).
Необходимо обычно моделировать отношения в обоих направлениях и указывать обратные связи соответственно. Базовые Данные используют эту информацию для обеспечения непротиворечивости графа объектов, если изменение внесено (см. Отношения Управления и Целостность Графа объектов). Для обсуждения некоторых причин, почему Вы не могли бы хотеть моделировать отношение в обоих направлениях, и некоторые проблемы, которые могли бы возникнуть, если Вы не делаете, посмотрите Однонаправленные Отношения.
Отношение удаляет правила
Отношение удаляет правило, указывает то, что должно произойти, если попытка предпринята для удаления исходного объекта. Отметьте формулировку в предыдущем предложении —, «если попытка предпринята …». Если отношение удаляет правило, установлен Отклонить, возможно, что не будет удален исходный объект. Рассмотрите снова отношение сотрудников отдела, и эффект, что различные удаляют правила, имеет.
Если существует по крайней мере один объект в месте назначения отношения, то исходный объект не может быть удален.
Например, если Вы хотите удалить отдел, необходимо гарантировать, что все сотрудники в том отделе сначала переданы в другое место (или уволены!) иначе отдел не может быть удален.
Установите обратную связь для объектов в месте назначения к нулю.
Например, если Вы удаляете отдел, устанавливаете отдел для всех текущих элементов к нулю. Это только целесообразно, если отношение отдела для сотрудника является дополнительным, или если Вы гарантируете установку нового отдела для каждого из сотрудников перед следующей работой сохранения.
Удалите объекты в месте назначения отношения.
Например, если Вы удаляете отдел, увольняете всех сотрудников в тот отдел одновременно.
Ничего не сделайте к объекту в месте назначения отношения.
Например, если Вы удаляете отдел, оставляете всех сотрудников, как они, даже если они все еще полагают, что принадлежат тому отделу.
- Отклонить
- Аннулировать
- Каскад
- Никакое действие
Должно быть ясно, что первые три из этих правил полезны при различных обстоятельствах. Для любого данного отношения Вам решать для выбора, который является самым надлежащим, в зависимости от бизнес-логики. Менее очевидно, почему Никакое правило Действия не могло бы быть полезным, с тех пор при использовании его у Вас есть возможность отъезда графа объектов в противоречивом состоянии (сотрудники, имеющие отношение к удаленному отделу).
Если Вы не используете правило Действия, Вам решать чтобы гарантировать, что сохраняется непротиворечивость графа объектов. Вы ответственны за установку любой обратной связи к значимому значению. Это может иметь преимущество в ситуации, где Вы имеете к - многие отношение и может быть большое количество объектов в месте назначения.
Управление отношениями и целостностью графа объектов
В целом программно управление отношениями является прямым. Для примеров того, как управлять отношениями программно, посмотрите Доступ и Изменение Свойств
Так как Базовые Данные заботятся об обслуживании непротиворечивости графа объектов для Вас, только необходимо изменить один конец отношения, и всеми другими аспектами управляют для Вас. Это применяется к к - один, к - многие и many-many отношения. Рассмотрите следующие примеры.
Отношение сотрудника менеджеру подразумевает обратное отношение между менеджером и сотрудниками менеджера. Если новый сотрудник присваивается определенному менеджеру, важно, чтобы менеджер был сделан знающий об этой ответственности. Новый сотрудник должен быть добавлен к списку менеджера отчетов. Точно так же, если сотрудник передается от одного отдела до другого, много модификаций должны быть сделаны, как проиллюстрировано на рисунке 1. Новый отдел сотрудника установлен, сотрудник отстранен из списка предыдущего отдела сотрудников, и сотрудник добавляется к списку нового отдела сотрудников.
Без Базовой платформы Данных необходимо записать несколько строк кода, чтобы гарантировать, что сохраняется непротиворечивость графа объектов. Кроме того, необходимо быть знакомы с реализацией класса Отдела, чтобы знать, должна ли обратная связь быть установлена (это может измениться, поскольку приложение развивается). Используя Базовую платформу Данных, все это может быть выполнено с одной строкой кода:
anEmployee.department = newDepartment; |
Также можно использовать:
[newDepartment addEmployeeObject:anEmployee]; |
(Для понимания деривации второй версии посмотрите Методы доступа Управляемого объекта.) Оба из них имеют тот же результирующий эффект: Путем ссылки на модель управляемого объекта платформа автоматически определяет от текущего состояния графа объектов, какие отношения должны быть установлены и который должен быть поврежден.
Отношения Many-Many
Вы определяете many-many отношение с помощью два к - много отношений. Первое к - многие отношение идет от первого объекта до второго объекта. Второе к - многие отношение идет от второго объекта до первого объекта. Вы тогда устанавливаете каждого, чтобы быть инверсией другого. (Если у Вас есть фон в управлении базой данных, и это вызывает Вас беспокойство, не волнуйтесь: при использовании хранилища SQLite Базовые Данные автоматически создают промежуточную объединяющую таблицу для Вас.)
Это работает даже на отношения назад к тому же объекту (часто называемый «рефлексивными» отношениями). Например, если у сотрудника может быть больше чем один менеджер (и у менеджера может быть больше чем один прямой отчет), то можно определить к - многие отношение directReports
от Сотрудника к себе, который является инверсией другого к - многие отношение, managers
, снова от Сотрудника к себе. Это проиллюстрировано на рисунке 2.
Отношение может также быть инверсией себя. Например, объект Лица может иметь a cousins
отношение, которое является инверсией себя.
Необходимо также рассмотреть, тем не менее, семантику отношения и как это должно быть смоделировано. Типичный пример отношения, первоначально моделирующегося как many-many отношение, это - инверсия себя, является «друзьями». Несмотря на то, что имеет место, что Вы - кузен своего кузена, нравится ли им он или нет, не обязательно имеет место, что Вы - друг своего друга. Для этого вида отношения необходимо использовать промежуточное звено («соединение») объект. Преимущество промежуточного объекта состоит в том, что можно также использовать его для добавления большей информации к отношению — например, объект «FriendInfo» мог бы включать некоторую индикацию относительно силы дружбы с «занимающим место» атрибутом. Это проиллюстрировано на рисунке 3
В этом примере Лицо имеет два к - много отношений к FriendInfo: friends
представляет исходных друзей лица, и befriendedBy
представляет тех, кто считает источник как их друг. FriendInfo представляет информацию об одной дружбе, “в одном направлении”. Приведенный пример отмечает, кто источник, и одно лицо, которое они считают своим другом. Если чувство будет взаимно, то будет соответствующий экземпляр где source
и friend
подкачиваются. Существует несколько других соображений при контакте с этим видом модели:
Для установления дружбы от одного лица другому необходимо создать экземпляр FriendInfo. Если оба человека друг как друг, необходимо создать два экземпляра FriendInfo.
Для повреждения дружбы необходимо удалить надлежащий экземпляр FriendInfo.
Удалить правило от Лица к FriendInfo должно быть каскадом. Если лицо удалено из хранилища, то экземпляр FriendInfo становится недопустимым, так должен также быть удален.
Как заключение, отношения от FriendInfo до Лица не должны быть дополнительными — экземпляр FriendInfo недопустим если
source
илиfriend
нуль.Для обнаружения, кто друзья одного лица необходимо агрегироваться весь
friend
места назначенияfriends
отношение, например:NSSet *personsFriends = [aPerson valueForKeyPath:@"friends.friend"];
С другой стороны, для обнаружения, кто полагает, что данное лицо их друзья необходимо агрегироваться весь
source
места назначенияbefriendedBy
отношение, например:NSSet *befriendedByPerson = [aPerson valueForKeyPath:@"befriendedBy.source"];
Однонаправленные отношения
Не строго необходимо смоделировать отношение в обоих направлениях. В некоторых случаях для, например может быть полезно не, когда к - многие отношение сможет иметь очень большое количество целевых объектов, и Вы, вероятно, будете, редко пересекать отношение (можно хотеть гарантировать, чтобы Вы излишне не давали сбой в большом количестве объектов в месте назначения отношения). Моделирование отношения в обоих направлениях, однако, налагает на Вас большое число ответственности, для обеспечения непротиворечивости графа объектов, для отслеживания изменений, и для управления отменой. Поэтому практике строго обескураживают. Это обычно только целесообразно к модели a к - одно отношение в одном направлении.
При создании модели с однонаправленными отношениями (отношения, где Вы не указали инверсии), Ваш граф объектов может закончиться в противоречивом состоянии.
Следующий пример иллюстрирует ситуацию, только моделирование отношения в направлениях могло бы вызвать проблемы. Рассмотрите модель, в которой у Вас есть два объекта, Сотрудник и Отдел, с к - одно отношение, «отдел», от Сотрудника к Отделу. Отношение является обязательным и имеет «отклонение», удаляют правило. Отношение не имеет инверсии. Теперь рассмотрите следующий пример кода:
Employee *employee; |
Department *department; |
// assume entity instances correctly instantiated |
[employee setDepartment:department]; |
[managedObjectContext deleteObject:department]; |
BOOL saved = [managedObjectContext save:&error]; |
Сохранение успешно выполняется (несмотря на то, что отношение является обязательным), как долго как employee
не изменяется никаким другим способом. Поскольку нет никакой инверсии для отношения Employee.department, employee
не отмечен, как изменено когда department
удален (и поэтому employee
не проверен для сохранения).
Если Вы тогда добавляете следующую строку кода:
id x = [employee department]; |
x
не будет отказ к «нигде», а не nil
.
Если с другой стороны отношение «отдела» имеет инверсию (и удалить правило не является Никаким Действием), все ведет себя «как ожидалось» с тех пор employee
отмечен, как изменено во время, удаляют распространение.
Это иллюстрирует, почему в целом необходимо избегать использования однонаправленных отношений. Двунаправленные отношения служат основой с дополнительной информацией, с которой лучше можно поддержать граф объектов. Если Вы действительно хотите использовать однонаправленные отношения, необходимо сделать часть этого обслуживания сами. В случае выше, это означало бы что после этой строки кода:
[managedObjectContext deleteObject:department]; |
необходимо записать:
[employee setValue:nil forKey:@"department"] |
Последующее сохранение теперь (правильно) перестанет работать из-за обязательного правила для отношения.
Отношения перекрестного хранилища
Необходимо бояться создавать отношения из экземпляров в одном персистентном хранилище к экземплярам в другом персистентном хранилище, поскольку это не поддерживается Базовыми Данными. Если необходимо создать отношение между объектами в различных хранилищах, Вы обычно используете выбранные свойства (см. Выбранные Свойства).
Выбранные свойства
Выбранные свойства представляют слабые, односторонние отношения. В домене сотрудников и отделов выбранное свойство отдела могло бы быть «недавней высокой разрешающей способностью» (у сотрудников нет инверсии к недавнему с высокой разрешающей способностью отношению). В целом выбранные свойства подходят лучше всего для моделирования отношений перекрестного хранилища, «слабо связанных» отношений и подобных переходных группировок.
Выбранное свойство походит на отношение, но оно отличается несколькими важными способами:
Вместо того, чтобы быть «прямым» отношением, значение выбранного свойства вычисляется с помощью запроса выборки. (Запрос выборки обычно использует предикат для ограничения результата.)
Выбранное свойство представлено массивом, не набором. Запрос выборки, связанный со свойством, может иметь упорядочивание вида, и таким образом выбранное свойство может быть упорядочено.
Выбранное свойство оценено лениво и впоследствии кэшируется.
В некотором отношении можно думать о выбранном свойстве, как являющемся подобным умному списку воспроизведения, но с важным ограничением, что это не динамично. Если объекты в целевом объекте изменяются, необходимо переоценить выбранное свойство, чтобы гарантировать, что это актуально. Вы используете refreshObject:mergeChanges:
когда объектный отказ затем запущен, для ручного обновления свойств — это заставляет запрос выборки, связанный с этим свойством выполняться снова.
Существует две специальные переменные, которые можно использовать в предикате выбранного свойства —$FETCH_SOURCE
и $FETCHED_PROPERTY
. Источник относится к определенному управляемому объекту, имеющему это свойство, и можно создать ключевые пути, происходящие с этим, например university.name LIKE [c] $FETCH_SOURCE.searchTerm
. $FETCHED_PROPERTY
выбранное описание свойства объекта. Описание свойства имеет userInfo словарь, который можно заполнить с любыми парами ключ/значение, которые Вы хотите. Можно поэтому изменить некоторые выражения в предикате выбранного свойства или (через ключевые пути) любой объект, с которым связан тот объект.
Чтобы понять, как переменные работают, рассмотрите выбранное свойство с целевым Автором объекта и предикатом формы, (university.name LIKE [c] $FETCH_SOURCE.searchTerm) AND (favoriteColor LIKE [c] $FETCHED_PROPERTY.userInfo.color)
. Если исходный объект имел атрибут searchTerm
равняйтесь «Кембриджу», и выбранное свойство имело пользовательский информационный словарь с ключевым «цветом» и «Зеленым» значением, тогда получающийся предикат будет (university.name LIKE [c] "Cambridge") AND (favoriteColor LIKE [c] "Green")
. Это соответствовало бы любым Авторам в Кембридже, любимый цвет которого является зеленым. Если бы Вы изменили значение searchTerm в исходном объекте в, скажем, «Дарем», то предикат был бы (university.name LIKE [c] "Durham") AND (favoriteColor LIKE [c] "Green")
.
Старшее значащее ограничение состоит в том, что Вы не можете использовать замены для изменения структуры предиката —, например, Вы не можете изменить предикат LIKE на составной предикат, и при этом Вы не можете изменить оператора (в этом примере, LIKE [c]
).