Как вы управляете и используете отношения "многие-многие" с основными данными?
Я создаю приложение и пытаюсь использовать основные данные, потому что кажется, что он одобрен objective-C способом создания системы хранения данных. Вариант использования, который я использую, связан с отношениями "многие-многие", как обычно вы видите в стандартной системе SQL. Я понимаю, что цель C не является базой данных и работает по-разному. Я также рассмотрел документацию здесь:
http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreData/Articles/cdRelationships.html#//apple_ref/doc/uid/TP40001857-SW10
И еще несколько других мест. И все же у меня все еще есть проблемы. Может ли кто-нибудь объяснить мне, что вы будете делать, если у вас есть вариант использования, где вам нужно будет использовать таблицу перекрестных ссылок SQL? Например:
Менеджеры | Сотрудники
У менеджера может быть несколько сотрудников, но у сотрудников также может быть несколько менеджеров. В SQL я бы создал таблицу перекрестных ссылок, а затем использовал это.
Пример: http://www.tomjewett.com/dbdesign/dbdesign.php?page=manymany.php
Может кто-нибудь объяснить, как вы могли бы это сделать в данных Core?
В соответствии с основной документацией данных они говорят следующее:
"Вы определяете отношения" многие-ко-многим ", используя отношения" два-ко-многим ". Отношение" от первого до многих "происходит от первого объекта ко второму объекту. Второе отношение ко многим относится ко второму объекту к первому (если у вас есть фон в управлении базой данных, и это вызывает у вас беспокойство, не беспокойтесь: если вы используете хранилище SQLite, Core Data автоматически создает промежуточную таблицу соединений для вы.)"
Но, кроме "не беспокоясь", я не знаю, как это могло бы работать?
Ответы
Ответ 1
Питер: "У меня девять боссов, Боб".
Боб: "Скажи еще раз?"
Питер: "Девять".
Извлеките свой мозг из базы данных. Не спрашивайте, как получить доступ к таблице перекрестных ссылок. Спросите, как найти сотрудников для менеджера или менеджеров для сотрудника.
Если вы используете пользовательский подкласс NSManagedObject, вы можете объявить свойства как задокументированные. Тогда вы можете просто сказать:
NSSet *mgrsEmployees = mgr.employees;
NSSet *employeesMgrs = employee.managers;
Это не даст вам всех сотрудников и всех менеджеров, только всех сотрудников этого менеджера и всех менеджеров для этого сотрудника. Чтобы изменить отношения:
[mgr addEmployeesObject:newEmployee];
[newEmployee addManagersObject:mgr]; // not necessary, automatic if you define inverse
[mgr removeEmployeesObject:transferredEmployee];
[transferredEmployee removeManagersObject:mgr]; // not necessary
[newMgr addEmployeesObject:transferredEmployee];
[transferredEmployee addManagersObject:newMgr]; // not necessary
Вам нужно только сделать одну из каждой пары операторов, и она будет неявно выполнять другую, если вы определили менеджеров и сотрудников как обратные друг от друга.
Если вы не используете пользовательский подкласс, доступ к нему будет немного более подробным
NSSet *mgrsEmployees = [mgr valueForKey:@"employees"];
NSSet *employeesMgrs = [employee valueForKey:@"managers"];
NSMutableSet *changeMgrsEmployees = [mgr mutableSetValueForKey:@"employees"];
[changeMgrsEmployees addObject:newEmployee];
// not necessary
NSMutableSet *changeEmployeesMgrs = [employee mutableSetValueForKey:@"managers"];
[changeEmployeesMgrs addObject:mgr];
Etc.
Ответ 2
Если ваш вопрос "как вы могли бы это сделать в основных данных", ответ будет точно так же, как вы описываете. Создайте отношения "многие" в каждом объекте и определите их как обратные к другим.
Если ваш вопрос "как это может работать", вам может показаться полезным взглянуть на базу данных sqlite, созданную из вашей модели, чтобы узнать, как это происходит. CoreData очень хорош в том, что вы не должны заботиться о деталях, но если вы настаиваете на понимании деталей, ничего не мешает вам смотреть на данные, чтобы увидеть, что они делают.
Как только у вас есть это место, вы должны пересечь отношения по мере необходимости, чтобы получить нужные вам атрибуты. Вы можете сделать это в коде, используя экземпляры NSManagedObject. Например:
NSManagedObject *manager = // get a reference to a manager here
NSSet *employees = [manager valueForKey:@"employees"];
for (NSManagedObject *employee in employees) {
NSString *employeeName = [employee valueForKey:@"name"];
// Do whatever else you want here
}
Этот пример также можно упростить, используя прямой доступ к свойствам, а не синтаксис KVO, но вы получите эту идею.
Если вы хотите более точно переходить от этого отношения "многие ко многим" как часть запроса на выборку, вы можете сделать некоторые вещи с предикатами, чтобы получить то, что вы хотите. Обратитесь к руководству по программированию предикатов Apple для примеров того, что вы можете поместить в предикат
Ответ 3
Скажем, у вас есть две сущности в вашей базе данных, сотрудники и менеджеры. Они выглядели бы примерно так в коде:
@interface Employee : NSManagedObject
{
}
@property (nonatomic, retain) NSNumber * id;
@property (nonatomic, retain) NSSet* managers;
@interface Manager : NSManagedObject
{
}
@property (nonatomic, retain) NSNumber * id;
@property (nonatomic, retain) NSSet* employees;
Итак, скажем, вы хотели получить всех сотрудников для менеджера номер 1, вам просто нужно получить объект-менеджер из базы данных:
NSNumber *managerID = [NSNumber numberWithInt:1];
NSEntityDescription * entityDescription = [NSEntityDescription entityForName:@"Manager" inManagedObjectContext:managedObjectContext];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %d", @"id", managerID];
[request setPredicate:predicate];
NSArray *array = [managedObjectContext executeFetchRequest:request error:&error];
Manager *manager = [array objectAtIndex:0];
и тогда у вас будут все сотрудники в собственности сотрудников:
NSSet *allHisEmployees = manager.employees;
Было бы точно так же получить менеджеров для данного сотрудника.
Я надеюсь, что это очистит вещи.
Ответ 4
Простой ответ заключается в том, чтобы пометить отношение как одно для многих с обоих концов при настройке основных данных в xCode. Это по существу создает много-много. Это в яблочном документе где-то, но я не могу найти URL.
Ответ 5
Возможно, вы застряли в том, как перейти от области абстрактных моделей данных к набору объектов, которые вы используете в коде. Если это так, посмотрите на использование mogenerator:
http://rentzsch.github.com/mogenerator/
Это утилита командной строки (не уверен, насколько хорошо работает XCode-интеграция в эти дни), где вы указываете ее на модели, и она дает вам множество объектов данных, которые вы можете использовать. Вы должны иметь имя объекта для каждого объекта в дополнение к имени объекта.
Сгенерированные объекты данных имеют вызовы, такие как employee.managers, которые предоставят вам набор объектов менеджера для сотрудника и наоборот.