Как вы управляете и используете отношения «многие ко многим» с основными данными? - PullRequest
19 голосов
/ 27 сентября 2011

Я создаю приложение и пытаюсь использовать базовые данные, потому что кажется, что это способ, утвержденный объективным 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

Может кто-нибудь объяснить, как вы могли бы сделать это в основных данных?

В соответствии с документацией по основным данным, они говорят следующее:

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

Но, кроме того, что" не беспокоиться ", я не знаю, как это может сработать?

Ответы [ 5 ]

55 голосов
/ 27 сентября 2011

Питер: "У меня есть девять боссов, Боб." Боб: Скажи еще раз? Петр: " Девять ."

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

Если вы используете пользовательский подкласс 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];

1020 * Etc. *

4 голосов
/ 27 сентября 2011

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

Если ваш вопрос «как это может сработать», вам может быть полезно взглянуть на базу данных 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 по программированию предикатов , где приведены примеры того, что вы можете вставить в предикат

2 голосов
/ 27 сентября 2011

Допустим, в вашей базе данных есть две сущности: сотрудники и менеджеры.Они будут выглядеть примерно так в коде:

@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;

Было бы точно так же, как получить менеджеров для данного сотрудника.

Iнадеюсь, это прояснит ситуацию

1 голос
/ 27 сентября 2011

Простой ответ - пометить отношение как один ко многим с обоих концов при настройке основных данных в xCode. Это в сущности создает много ко многим. Это где-то в документах Apple, но я не могу найти URL.

0 голосов
/ 27 сентября 2011

Возможно, вы застряли на том, как добраться от области абстрактной модели данных до набора объектов, которые вы используете в коде.Если это так, посмотрите на использование mogenerator:

http://rentzsch.github.com/mogenerator/

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

Сгенерированные объекты данных имеют вызовы, такие как employee.managers, которые дают вам набор сущностей Manager для сотрудника, инаоборот.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...