Отношения и извлеченные свойства Core Data в среде Cocoa, Mac OS X, iOS

Cocoa

Есть целый ряд вещей, которые вы должны решить, когда вы создаете отношения. Каково назначение сущности? Является ли оно отношением к одному или ко многим? Есть ли в этом необходимость? Если это ко-многим, есть максимальное или минимальное число объектов, которые могут быть в отношениях? Что должно произойти, когда исходный объект удален? Вы можете получить ответы на все эти модели. Одним из особенно интересных случаев -отношение многие-ко-многим, есть два способа смоделировать их, и какой из них вы выберете, будет зависеть от семантики схемы.

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

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

Отношения определяются в модели

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

Основы отношений

Отношение определяет сущность или родительскую сущность, объекта назначения. Она может быть одинаковой, как у сущности так и у источника (рефлексивные отношения). Отношения не должны быть однородными. Если сущность Employee имеет две подсущности, скажем, Manager и Flunky, то сотрудники данного отдела могут быть составлены ​​из Employees (если Employee не абстрактная сущность), Managers, Flunkies, или любой их комбинацией.

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

Вы также можете поместить верхний и нижний пределы по количеству объектов на назначение ко-многим. Нижняя граница не обязательно должна быть равна нулю. Вы можете, если вы хотите указать, что количество сотрудников в отделе должно лежать в пределах от 3 до 40. Также можно указать отношения, как обязательные или необязательные. Если связь не является обязательной, то для того, чтобы быть действительной должна быть объектом или объектами в назначенном отношении.

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

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

@interface Widget : NSObject
{
    Sprocket *sprocket;
}

Если вы создаете экземпляр Widget, например, экземпляр Sprocket не создается, вы пишете код, чтобы заставить это произойти (например, путем переопределения метода init). Аналогично, если Вы определяете сущность Address, а не отношение к одному из Employee на Address, то просто создание экземпляра Employee не создает новый экземпляр Address. Аналогично, если Вы определяете не обязательное отношение ко-многим из Employee на Address с минимальным кол-вом 1, то простое создание экземпляра Employee не создает новый экземпляр Address.

Обратные связи

Большинство отношений по своей природе двунаправленные. Если Department имеет отношение ко-многим к Employees, которые работают в Department, существует обратная связь от Employees в Department. Основным исключением является излеченное свойство, которое представляет собой слабое одностороннее отношение, не имеющее никакой связи с источником.

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

Отношения, правила удаления

Правило удаления в отношениях определяет, что должно произойти, если осуществляется попытка удалить исходный объект. Обратите внимание на формулировку в предыдущем предложении-", если попытка ...". Если правило удаления отношения имеет значение Deny, вполне возможно, что исходный объект не будет удален. Рассмотрим снова отношения отдела с сотрудниками (employees), и различные правила удаления.

Deny
  • Если есть хотя бы один объект в отношениях назначения, то исходный объект не может быть удален.

    Например, если вы хотите удалить отдел (department), вы должны убедиться, что все сотрудники (employees) этого отдела, сначала переводятся в другое место (или уволены!), Иначе отдел (department) не может быть удален.

Nullify
  • Устанавливает обратную связь для объектов в назначении в нуль.

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

Cascade
  • Удалит объекты в назначенных отношениях.

    Например, если вы удалите отдел (department), то уволите всех сотрудников (employees) этого отдела в то же самое время.

No Action
  • Ничего не делает с объектами в назначенных отношениях.

    Например, если вы удалите отдел (department), оставит всех сотрудников (employees), как они есть, даже если они по-прежнему считают, что они принадлежат к этому отделу.

Должно быть ясно, что первые три из этих правил являются полезными в различных ситуациях. Любое данное отношение это Ваш выбор, в зависимости от бизнес-логики. Менее очевидно, почему может быть использовано правило No Action, так как если вы его используете вы имеете возможность оставить граф объектов в несогласованном состоянии (сотрудники (employees), имеющие отношение к удаленному отделу (department)).

Если вы используете правило No Action, Вам следует убедиться, что последовательность графа объектов сохраняется. Вы несете ответственность за установление любой обратной связи в валидное значение. Данное правило может быть полезно в ситуации, когда у вас есть отношение ко-многим и может быть большое количество назначенных объектов.

Управление отношениями и целостность объекта графа

В общем, программное манипулирование отношениями просто. Для примера того, как манипулировать отношениями программно, см. "Доступ и изменение свойств".

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

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

Core Data Управление отношениями и целостность объекта графа

Без Core Data framework, вы должны написать несколько строк кода, чтобы убедиться, что согласованность объектов графа сохраняется. Более того, вы должны быть знакомы с реализацией класса Department, чтобы узнать, является ли обратная связь обязательной к установлению ​​(это может измениться по мере развития приложения). С использованием Core Data framework, все это может быть достигнуто, из одной строки кода:

anEmployee.department = newDepartment;

Или в качестве альтернативы можно использовать:

[newDepartment addEmployeeObject:anEmployee];

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

Отношения многие ко многим

Вы определяете отношения многие-ко-многим с помощью двух отношений ко-многим. Первым отношением ко-многим идет от первой сущности на вторую сущность. Второе отношение ко-многим идет от второго объекта сущности к первой. Затем установите которое будет обратным другому. (Если у вас есть опыт работы в области управления базами данных, и это вызывает у вас беспокойство, не волнуйтесь: если вы используете SQLite хранилище, Core Data автоматически создает промежуточную таблицу соединения за вас.)

Важно: Вы должны определить многие-ко-многим в обоих направлениях, то есть, вы должны указать два отношения, каждое из которых обратно другому. Вы не можете просто определить отношение ко-многим в одном направлении и пытаться использовать его как многие-ко-многим. Если вы это сделаете, вы будете в конечном итоге иметь проблемы с целостностью.

Это работает даже для обратных отношений на тот же объект (часто называемые «рефлексивные» отношения). Например, если работник (employee) может иметь более одного менеджера (manager) (и менеджера может иметь более одного прямого доклада), то вы можете определить отношение ко-многим DirectReports от сотрудника к самому себе, что является обратным отношением ко-многим другого сотрудника, опять же из сотрудников к себе. Это показано на рисунке ниже.

Core Data определение  обратных отношений

Отношения также могут быть обратным сама от себя. Например, сущность Persone может иметь отношение cousins (родственник), которое является обратным к себе.

Важно: В OS X v10.4, многие-ко-многим не работает с хранилищем SQLite, если отношения обратны сами себе (например, как в случае с cousins).

Вы должны также рассмотреть, семантику отношений и как она должна быть смоделирована. Типичным примером отношений, которые первоначально моделируются как многие-ко-многим это обратная сама от себя "friends" (друзья). Хотя на деле, то, что вы двоюродный брат вашего двоюродного брата, нравится ли Вам или нет, это не обязательно говорит о том, что вы друзья по отношению к друг к другу. Для такого рода отношений, вы должны использовать промежуточные ("join" (Объединение)) сущности. Преимуществом промежуточных сущностей является то, что вы также можете использовать их, чтобы добавить информацию в отношения, например "FriendInfo" сущность может включать в себя некоторое представление о силе дружбы с атрибутом "ranking" (рейтинг). Пример показан на рисунке ниже.

Core Data промежуточные ("join" (Объединение)) сущности.

В этом примере, Person имеет отношение два ко-многим, чтобы FriendInfo: friends представлял источника друга человека, и befriendedBy представлял тех, кто как считает источник, его друг. FriendInfo представляет информацию об одной дружбе, "в одном направлении". Данный экземпляр отмечает, кто является источником, и один человек, которого они считают своим другом. Если это чувство взаимно, то будет соответствующий случай, когда источник и друг меняются местами. Есть несколько других соображений при работе с такого рода моделью:

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

Однонаправленные отношения

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

Если вы создаете модель с однонаправленными отношениеми (отношения, которые вы указали не имеют обратного), ваш граф объекта может оказаться в несогласованном состоянии.

Следующий пример иллюстрирует ситуацию, когда только моделирование отношений в одном направлений может вызвать проблемы. Рассмотрим модель, в которой у вас есть две сущности, Employee (сотрудник) и Department (отдел), с отношением к-одному "department", от сотрудника в отдел. Отношение не является обязательным и имеет правило удаления "deny". Отношение не имеет обратного. Теперь рассмотрим следующий пример кода:

Employee *employee;
Department *department;

// Предположим экземпляры сущностей корректны

[employee setDepartment:department];
[managedObjectContext deleteObject:department];
BOOL saved = [managedObjectContext save:&error];

Сохранение успешно (несмотря на то, что отношение не обязательно), пока employee не изменился любым другим способом. Поскольку что нет обратного для Employee.department отношения, employee не был помечен как измененный, когда отдел был удален (и, следовательно, работник не утвержден на запись).

Если вы затем добавьте следующие строки кода:

id x = [employee department];

х будет выброшен в «никуда», а не nil.

С другой стороны, если, отношение "department" имеет обратное (и правило удаления не No Action), все ведет себя "как ожидалось", так как employee отмечен как изменившийся при распространении удаления.

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

[managedObjectContext deleteObject:department];

вы должны написать:

[employee setValue:nil forKey:@"department"];

Кросс-хранилищные отношения

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

Извлекаемые свойства

Извлекаемые свойства представляют слабые, в одну сторону отношения. В области сотрудников (employees) и подразделений (departments), извлекаемое свойство подразделения может быть "последний нанятый" (сотрудники не имеющие обратной связи к отношениям недавно нанятым). В общем, извлекаемые свойства лучше всего подходит для моделирования кросс-хранилищных отношений, "слабосвязанных" отношенийя, и подобных переходные групп.

Извлекаемые свойства, как отношения, но они отличаются по нескольким важным направлениям:

  • Вместо того, чтобы быть «прямыми» отношениями, значение извлекаемого свойства рассчитывается по запросу выборки. (Выборка запроса обычно использует предикат, чтобы ограничить результат).
  • Извлекаемые свойства представлены массивом, а не множеством. Полученный запрос, связанный со свойством может иметь направление сортировки, и таким образом извлекаемые свойства могут быть отсортированы.
  • Извлекаемые свойства обрабатываются лениво, и впоследствии кэшируются.

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

Есть две специальные переменные, которые можно использовать в предикате извлекаемого свойства $FETCH_SOURCE и $FETCHED_PROPERTY. Источник ссылается на конкретный управляемый объект, который обладает этим свойством, и вы можете создать ключ пути, которые возникают при, например, university.name LIKE [c] $FETCH_SOURCE.searchTerm. $FETCHED_PROPERTY извлекает описание свойства сущности. Описание свойства имеет userInfo словарь, который можно заполнить теми, парами ключ-значение, какими хотите. Таким образом, можно изменить некоторые выражения в предикате извлекаемых свойств или (с помощью ключ путей) любого объекта, к которому относится объект.

Наиболее существенным ограничением является то, что вы не можете использовать подстановки для изменения структуры предиката, например, вы не можете изменить LIKE предикат соединения предиката, и вы не можете сменить оператор (в данном примере, как [с]). Кроме того, в OS X версии 10.4, это работает только с XML и бинарными хранилищами, а в случае SQLite не будет генерировать соответствующий SQL.

 
 
homeЗаметили ошибкукарта сайта 
   Made on a Mac