Поведение первичного ключа в Core Data iPhone - PullRequest
3 голосов
/ 10 ноября 2009

Я создаю приложение, которое анализирует каналы из xml и сохраняет их с использованием Core Data. Вопрос, с которым я сейчас занимаюсь, - это дублирующиеся записи. Каждый фид, который я анализирую, содержит уникальный идентификатор, который я получаю в своей модели как int. Теперь мне нужно сообщить Core Data , а не , чтобы хранить эту сущность, если другая сущность с таким же идентификатором уже существует.

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

Story.id (int) - primary key
Story.title (NSString)
Story.date (NSDate)

Каков наилучший способ реализовать это?

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

Ответы [ 2 ]

8 голосов
/ 10 ноября 2009

Я вижу два способа сделать это. Мне кажется, что последний (предложенный вами метод) является лучшим решением.

Я изменил id на primaryKey, так как не думаю, что было бы неплохо использовать id в качестве имени переменной или метода в Object-C, поскольку это ключевое слово. Я мог бы работать, я никогда не пробовал. Также я предположил, что primaryKey - это NSNumber, поскольку именно так будет храниться в Базовых данных.

Метод Один будет каждый раз выполнять запрос выборки в контексте:

for (id data in someSetOfDataToImport) {
    NSFetchRequest * request = [[NSFetchRequest alloc] init];

    [request setEntity:[NSEntityDescription entityForName:@"Story" inManagedObjectContext:context]];
    [request setPredicate:[NSPredicate predicateWithFormat:@"primaryKey = %d", primaryKey]];
    NSUInteger count = [context countForFetchRequest:request error:nil];
    [request release];

    if (count > 0)
        continue;

    // Insert data in Managed Object Context
}

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

NSFetchRequest * request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:@"Story" inManagedObjectContext:context]];
NSArray * allStories = [context countForFetchRequest:request error:nil];
[request release];

NSMutableArray * allPrimaryKeys = [[allStories valueForKeyPath:@"@distinctUnionOfObjects.primaryKey"] mutableCopy];

for (id data in someSetOfDataToImport) {
    if ([allPrimaryKeys containsObject:data.primaryKey])
        continue;

    [allPrimaryKeys addObject:data.primaryKey];

    // Insert data in Managed Object Context
}

[allPrimaryKeys release];
3 голосов
/ 11 ноября 2009

Я бы предостерег вас от преждевременной оптимизации. Это корень всего программирования зла и пустая трата времени.

Честно говоря, на iPhone практически невозможно получить такой огромный объектный граф, который вы начинаете замечать, что все утомляет. Я не могу представить, что вы обрабатываете сотни уникальных XML-каналов каждую секунду.

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

...