В нашем разрабатываемом приложении мы используем Core Data с хранилищем sqlite для хранения наших данных. Объектная модель для нашего приложения сложна. Кроме того, общий объем данных, обслуживаемых нашим приложением, слишком велик, чтобы вписаться в комплект приложений для iOS (iPhone/iPad/iPod Touch). Из-за того, что наши пользователи, как правило, заинтересованы только в подмножестве данных, мы разделили наши данные таким образом, что приложение поставляется с подмножеством (хотя и около 100 МБ) объектов данных в приложение. Наши пользователи имеют возможность загружать дополнительные данные (размером от 5 МБ до 100 МБ) с нашего сервера после того, как они платят за дополнительное содержимое через покупки iTunes в приложении. Инкрементные файлы данных (существующие в хранилищах хранилища sqlite) используют ту же версию xcdatamodel, что и данные, поставляемые вместе с пакетом; в объектной модели нулевые изменения. Инкрементные файлы данных загружаются с нашего сервера в виде файлов с поддержкой gzipped sqlite. Мы не хотим раздувать наш пакет приложений, отправляя инкрементное содержимое с помощью приложения. Кроме того, мы не хотим полагаться на запросы через webservice (из-за сложной модели данных). Мы протестировали загрузку инкрементных данных sqlite с нашего сервера. Мы смогли добавить загруженное хранилище данных в общедоступное приложение persistentStoreCoordinator.
{
NSError *error = nil;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:defaultStoreURL options:options error:&error])
{
NSLog(@"Failed with error: %@", [error localizedDescription]);
abort();
}
// Check for the existence of incrementalStore
// Add incrementalStore
if (incrementalStoreExists) {
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:incrementalStoreURL options:options error:&error])
{
NSLog(@"Add of incrementalStore failed with error: %@", [error localizedDescription]);
abort();
}
}
}
Однако есть две проблемы с этим.
- Результаты выборки данных (например, с помощью NSFetchResultController) отображаются с данные от incrementalStoreURL, добавленные к концу данных из defaultStoreURL.
- Некоторые объекты дублируются. Существует множество объектов с данные только для чтения в нашей модели данных; они дублируются, когда мы добавляем второй persistentStore для persistentStoreCoordinator.
В идеале мы хотели бы, чтобы Core Data объединил графы объектов из двух постоянных хранилищ в один (нет общих отношений между данными из двух хранилищ во время загрузки данных). Кроме того, мы хотели бы удалить дубликаты объектов. В Интернете мы увидели пару вопросов от людей, пытающихся сделать то же самое, что и мы, - этот ответ и этот ответ. Мы читаем Блог Marcus Zarra по импорту больших наборов данных в Core Data. Однако ни одно из решений, которые мы видели, не сработало для нас. Мы не хотим вручную считывать и сохранять данные из инкрементного хранилища в хранилище по умолчанию, поскольку мы считаем, что это будет очень медленным и подверженным ошибкам на телефоне. Есть ли более эффективный способ слияния?
Мы попытались решить проблему, выполнив ручную миграцию следующим образом. Однако нам не удалось успешно добиться слияния. Мы не совсем поняли решение, предложенное в ответах 1 и 2, упомянутых выше. Блог Marcus Zarra затронул некоторые из проблем, которые мы имели в начале нашего проекта, импортируя наш большой набор данных в iOS.
{
NSError *error = nil;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSMigrationManager *migrator = [[NSMigrationManager alloc] initWithSourceModel:__managedObjectModel destinationModel:__managedObjectModel];
if (![migrator migrateStoreFromURL:stateStoreURL
type:NSSQLiteStoreType
options:options
withMappingModel:nil
toDestinationURL:destinationStoreURL
destinationType:NSSQLiteStoreType
destinationOptions:nil
error:&error])
{
NSLog(@"%@", [error userInfo]);
abort();
}
}
Кажется, что автор ответа 1 закончил чтение своих данных из инкрементного хранилища и сохранение в хранилище по умолчанию. Возможно, мы неправильно поняли решение, предложенное в обеих статьях 1 и 2. Размер наших данных может помешать нам вручную считывать и повторно вставлять наши инкрементные данные в хранилище по умолчанию. Мой вопрос: какой самый эффективный способ получить графы объектов из двух постоянных хранилищ (имеющих один и тот же объектModel), чтобы объединиться в один постоянный хранилище?
Автоматическая миграция работает очень хорошо, когда мы добавляем новые атрибуты сущностей к графам объектов или изменяем отношения. Есть ли простое решение для слияния подобных данных с одним и тем же постоянным хранилищем, которое будет достаточно устойчивым, чтобы останавливаться и возобновляться - как автоматическая миграция выполняется?