основные данные, извлекающие данные из наборов с отношениями «многие ко многим»

Я новичок в основных данных и все еще пытаюсь понять это. У меня есть проблема, на решение которой я потратил несколько часов. Я просто не могу решить это и надеялся, что кто-то может мне помочь.

Я пока не могу публиковать изображения, поэтому вот ссылка на мою модель данных:

http://yourpcsolution.net/model.png

Каждое отношение имеет обратное. В игре может быть много периодов, а в периоде может быть много игроков. Игрок может находиться более чем в одном Периоде.

Вот мой код для заполнения БД:

- (void) prepareDB {
Games *game = [NSEntityDescription insertNewObjectForEntityForName:@"Games" inManagedObjectContext:self.managedObjectContext];
game.date = [NSDate date];
game.name = @"Game 1";

Periods *period = [NSEntityDescription insertNewObjectForEntityForName:@"Periods" inManagedObjectContext:self.managedObjectContext];

period.date = [NSDate date];
period.name = @"1st Period";

NSMutableSet *gameSet = [[NSMutableSet alloc] initWithObjects:period, nil];

game.periods = gameSet;

Players *player = [NSEntityDescription insertNewObjectForEntityForName:@"Players" inManagedObjectContext:self.managedObjectContext];

player.name = @"Player1";

NSMutableSet *playerSet = [[NSMutableSet alloc] initWithObjects:player, nil];

period.players = playerSet;

NSError *error;
if (![self.managedObjectContext save:&error]) {
    NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
}
}

Я думаю, что это правильный способ добавления данных, потому что при просмотре базы данных sql данные есть. Моя проблема заключается в попытке найти игроков, принадлежащих к каждому периоду. Поскольку периоды — это набор в играх, а игроки — это набор в периодах в основных данных. Поэтому я не могу получить игроков, перейдя: game.periods.players

Вот мой код для получения периода, и в журнале xcode я получаю сообщение об ошибке:

"Relationship 'players' fault on managed object (0x8e72bc0) <Periods: 0x8e72bc0>
(entity: Periods; id: 0x8e727c0 <x-coredata://7F63902B-FCB6-4ACA-BB40-904755D37A4A/Periods/p1>;
data: {\n    date = \"2013-07-09 19:35:48 +0000\";\n
games = \"0x8e6d760 <x-coredata://7F63902B-FCB6-4ACA-BB40-904755D37A4A/Games/p1>\";\n
name = \"1st Period\";\n    players = \"<relationship fault: 0x9840330 'players'>\";\n})"

Мой код для получения периода:

NSString *firstPeriod = @"1st Period";
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == %@", firstPeriod];
[request setEntity:[NSEntityDescription entityForName:@"Periods" inManagedObjectContext:self.managedObjectContext]];
[request setPredicate:predicate];

NSArray *period = [self.managedObjectContext executeFetchRequest:request error:&error];

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

Верна ли моя модель данных? Как я должен получать данные? Любая помощь или совет приветствуются.


person TazmanNZL    schedule 09.07.2013    source источник


Ответы (1)


Чтобы получить всех игроков за определенный период, должно работать следующее:

NSString *firstPeriod = @"1st Period";

NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:@"Players" inManagedObjectContext:self.managedObjectContext]];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY periodsin.name == %@", firstPeriod];
[request setPredicate:predicate];

NSArray *players = [self.managedObjectContext executeFetchRequest:request error:&error];

«ЛЮБОЙ» в предикате необходим, потому что каждый игрок связан с несколькими периодами.

Примечание. Тип данных отношения "ко многим" — NSSet, а не NSMutableSet.

ДОБАВЛЕНО: чтобы получить все периоды для данного игрока, вы можете использовать следующий запрос на выборку:

Players *givenPlayer = ... ; // the given player
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:@"Periods" inManagedObjectContext:self.managedObjectContext]];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY players == %@", givenPlayer];
[request setPredicate:predicate];
NSArray *periods = [self.managedObjectContext executeFetchRequest:request error:&error];

Кроме того, вы можете получить доступ к отношениям напрямую:

Players *givenPlayer = ... ; // the given player
NSArray *periods = [givenPlayer.periodsin allObjects]; // "allObjects" converts NSSet to NSArray
person Martin R    schedule 09.07.2013
comment
Я использовал NSMutableSet, чтобы добавлять в него игроков, а затем назначал его набору game.periods. Знаете ли вы, почему я получаю сообщение об ошибке при попытке получить период?? - person TazmanNZL; 10.07.2013
comment
Есть ли простой способ вернуть массив периодов, к которым принадлежит конкретный игрок. Например, если бы Player1 был в 3 разных периодах, как бы я написал для этого запрос на выборку? - person TazmanNZL; 10.07.2013
comment
1) Ошибка — это просто объект-заполнитель (а не ошибка). Свойства извлекаются автоматически при доступе к ним. Ошибки задокументированы в Руководстве по программированию основных данных. - 2) См. обновленный ответ. - Надеюсь, это поможет! - person Martin R; 10.07.2013