2013-02-26 9 views
9

Próbuję przeprowadzić migrację danych podstawowych systemu iOS wymagającą modelu mapowania. Podstawowe dane nie mogą z jakiegoś powodu korzystać z modelu odwzorowania, a powrót do automatycznej, lekkiej migracji.Nie znaleziono odpowiedniego modelu odwzorowania do podstawowej migracji danych

Włączam opcję MigrationDebug, aby uzyskać więcej informacji, a to, co widzę, nie ma sensu. Skórki źródłowe i docelowe modelu odwzorowania są identyczne, ignorując kolejność, do źródłowego i docelowego obiektu ManagedObjectModels. Wygląda na to, że należy użyć modelu odwzorowania, ale dziennik mówi: "nie znaleziono odpowiedniego modelu odwzorowania".

Oto (pomijana) log:

CoreData: annotation: (migration) will attempt automatic schema migration 
CoreData: annotation: (migration) looking for mapping model with 
source hashes: 
{ 
    TSBaseEntity = <4797118c 50068f2f f544d9a9 4884720b 55ec7e4d 0d4c8f4e 1ee44be3 b06d2edc>; 
    TSBuyer = <91e837d1 3f348913 eff634d6 6fb9b3a6 747e2390 fbdc4ae6 32cc56d6 7582d4a8>; 
    ... 
} 
destination hashes: { 
    TSBaseEntity = <4797118c 50068f2f f544d9a9 4884720b 55ec7e4d 0d4c8f4e 1ee44be3 b06d2edc>; 
    TSBuyer = <e316a857 8919c4be eef15387 5c67a21b 67d32919 99ead438 1ff93c05 2e065fcc>; 
    ... 
} 
CoreData: annotation: (migration) checking mapping model at path file://localhost/Users/xandrews/Library/Application%20Support/iPhone%20Simulator/6.1/Applications/0A84951E-21FC-47C0-A1B7-F880ACB672C4/Dev.app/Migrate_0_5_24To_0_5_27.cdm 
source hashes: 
{(
    <4797118c 50068f2f f544d9a9 4884720b 55ec7e4d 0d4c8f4e 1ee44be3 b06d2edc>, 
    <91e837d1 3f348913 eff634d6 6fb9b3a6 747e2390 fbdc4ae6 32cc56d6 7582d4a8>, 
    ... 
)} 
destination hashes: {(
    <4797118c 50068f2f f544d9a9 4884720b 55ec7e4d 0d4c8f4e 1ee44be3 b06d2edc>, 
    <e316a857 8919c4be eef15387 5c67a21b 67d32919 99ead438 1ff93c05 2e065fcc>, 
    ... 
)} 
CoreData: annotation: (migration) no suitable mapping model found 
CoreData: annotation: (migration) inferring a mapping model between data models with 
source hashes: ... 

Odpowiedz

8

Model odwzorowania wygenerowany przez Xcode 4 nie generuje poprawnych skrótów potrzebnych do migracji. Można porównać wyjście z dziennika migracji do mieszań Twojego pliku mapowania za pomocą poniższego kodu:

NSString *mappingModelPath = [[NSBundle mainBundle] pathForResource:@"MappingFile" ofType:@"cdm"]; 
    NSMappingModel *mappingModel = [[NSMappingModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:mappingModelPath]]; 

    for (NSEntityMapping *entityMapping in mappingModel.entityMappings) { 
     NSLog(@"%@: %@", entityMapping.sourceEntityName, entityMapping.sourceEntityVersionHash); 
     NSLog(@"%@: %@", entityMapping.destinationEntityName, entityMapping.destinationEntityVersionHash); 
    } 

Zobaczysz, że te nie są zgodne z mieszań w wyjściu dziennika migracji.

Rozwiązaniem jest generowanie pliku mapowania w Xcode 5.

+0

Więc nie możemy użyć narzędzia migracji w Xcode 4.6.2, ponieważ generuje zły plik ?? –

+2

Nie wiem, czy to jest rozwiązanie, ale z pewnością jest rozwiązaniem. Używając pliku wygenerowanego przez Xcode 5 DP4 pracował dla mnie. –

+1

Dla Xcode 4 spróbuj [ta odpowiedź] (http://stackoverflow.com/a/9428260/1402846). – Pang

0

Model mapowanie prawdopodobnie nie jest wystarczająca do obsługi migracji. W takim przypadku model mapowania nie zostanie załadowany, nawet jeśli pasuje do modelu źródłowego i docelowego.

Napisz test na migrację. Ponownie wykonaj zmiany w swoim modelu krok po kroku i przetestuj migrację. W ten sposób znajdziesz zmianę, która zapobiega ładowaniu modelu mapowania.

Szukanie: Zmiana nazwy atrybutów lub tworzenie atrybutów bez określania wartości domyślnych. Zmiana atrybutów na nieobowiązkowe.

W tych przypadkach należy ręcznie określić zachowanie w modelu odwzorowania.

+0

Mam ten sam problem i chociaż ja już przepisany model odwzorowania od podstaw nadal nie jestem w stanie uzyskać jego pracy. Migracja nie powiedzie się bez względu na to, co próbuję. – s1m0n

0

Miał ten sam problem. Usunąłem encję i odpowiednio zmieniono nazwy pól relacji. Po raz pierwszy spróbowałem użyć lekkiej migracji, dlatego określono nazwy przemian dla tych relacji. Z powodu niedopatrzenia pomieszałem pola używane dla "identyfikatora zmiany nazwy" i "modyfikatora skrótu". Po poprawieniu wszystko działa zgodnie z oczekiwaniami.

3

W swojej metodzie persistentStoreCoordinator dać tę linię kodu

NSDictionary *options=[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],NSMigratePersistentStoresAutomaticallyOption,[NSNumber numberWithBool:YES],NSInferMappingModelAutomaticallyOption, nil]; 

Jeśli to robi pomaga to trzeba iść za realizowane użytkownika migracji. Będziesz musiał stworzyć model odwzorowania przy użyciu modelu źródłowego i docelowego. W takim przypadku zestawu,

NSDictionary *options=[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],NSMigratePersistentStoresAutomaticallyOption,[NSNumber numberWithBool:NO],NSInferMappingModelAutomaticallyOption, nil]; 

Tworzenie metadanych douce z następującym kodem

if (sourceMetadata) { 
     NSString *configuration = nil; 
     NSManagedObjectModel *destinationModel = [self.persistentStoreCoordinator managedObjectModel]; 

     //Our Source 1 is going to be incompatible with the Version 2 Model, our Source 2 won't be... 
     BOOL pscCompatible = [destinationModel isConfiguration:configuration compatibleWithStoreMetadata:sourceMetadata]; 
     NSLog(@"Is the STORE data COMPATIBLE? %@", (pscCompatible==YES) [email protected]"YES" :@"NO"); 

     if (pscCompatible == NO) { 
      migrationSuccess = [self performMigrationWithSourceMetadata:sourceMetadata toDestinationModel:destinationModel]; 
     } 
    } 
    else { 
     NSLog(@"checkForMigration FAIL - No Source Metadata! \nERROR: %@", [error localizedDescription]); 
    } 

i realizować następujące funkcje

- (BOOL)performMigrationWithSourceMetadata :(NSDictionary *)sourceMetadata toDestinationModel:(NSManagedObjectModel *)destinationModel 
{ 
    BOOL migrationSuccess = NO; 
    //Initialise a Migration Manager... 
    NSManagedObjectModel *sourceModel = [NSManagedObjectModel mergedModelFromBundles:nil 
                    forStoreMetadata:sourceMetadata]; 
    //Perform the migration... 
    if (sourceModel) { 
     NSMigrationManager *standardMigrationManager = [[NSMigrationManager alloc] initWithSourceModel:sourceModel 
                         destinationModel:destinationModel]; 
     //Retrieve the appropriate mapping model... 
     NSMappingModel *mappingModel = [NSMappingModel mappingModelFromBundles:nil 
                   forSourceModel:sourceModel 
                   destinationModel:destinationModel]; 
     if (mappingModel) { 
      NSError *error = nil; 
      NSString *storeSourcePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent:@"Recipes.sqlite"]; 
      NSURL *storeSourceUrl = [NSURL fileURLWithPath: storeSourcePath]; 
      NSString *storeDestPath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent:@"Recipes2.sqlite"]; 
      NSURL *storeDestUrl = [NSURL fileURLWithPath:storeDestPath]; 

      //Pass nil here because we don't want to use any of these options: 
      //NSIgnorePersistentStoreVersioningOption, NSMigratePersistentStoresAutomaticallyOption, or NSInferMappingModelAutomaticallyOption 
      NSDictionary *sourceStoreOptions = nil; 
      NSDictionary *destinationStoreOptions = nil; 

      migrationSuccess = [standardMigrationManager migrateStoreFromURL:storeSourceUrl 
                     type:NSSQLiteStoreType 
                    options:sourceStoreOptions 
                  withMappingModel:mappingModel 
                  toDestinationURL:storeDestUrl 
                  destinationType:NSSQLiteStoreType 
                  destinationOptions:destinationStoreOptions 
                     error:&error]; 
      NSLog(@"MIGRATION SUCCESSFUL? %@", (migrationSuccess==YES)[email protected]"YES":@"NO"); 
     } 
    } 
    else { 
     //TODO: Error to user... 
     NSLog(@"checkForMigration FAIL - No Mapping Model found!"); 
     abort(); 
    } 
    return migrationSuccess; 
} 
1

Po dodatkowych wojsk dochodzenia znalazłem się ja przeżywa ten sam problem jak wspomniano tutaj (Core Data migration fails for to-one relationship). Ustawienia minimalne do 1 zamiast minimalnego w moim związku sprawiły, że Dane podstawowe używają mojego niestandardowego modelu odwzorowania. Chociaż nie jestem pewien zakładam, że jest to błąd w danych podstawowych.
Wymagało to jednak zmiany pierwotnego (1.0) modelu odwzorowania (którego użytkownicy już używali). Naprawiona przeze mnie poprawka polega na utworzeniu nowego modelu odwzorowania między 1.0 a 2.0 o nazwie 1.5. Jedyną rzeczą, która różni się 1,5 w porównaniu z 1,0, jest minimum relacji, która jest w 1.5 ustawiona na 1. Teraz mogę pozwolić Core Data wykonać niewielką migrację z wersji 1.0 na 1.5, a następnie przeprowadzić własną migrację z 1,5 do 2,0. Chociaż może to być hacky rozwiązanie, działa idealnie.Wkleiłem kod, który obsługuje migrację poniżej.

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 
    if (persistentStoreCoordinator != nil) { 
     return persistentStoreCoordinator; 
    } 

    NSURL *storeUrl = [NSURL fileURLWithPath:[[self applicationDocumentsDirectory] stringByAppendingPathComponent:@"Project.sqlite"]]; 
    NSError *error; 

    NSDictionary *storeMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType URL:storeUrl error:&error]; 

    if (! [[self managedObjectModel] isConfiguration:nil compatibleWithStoreMetadata:storeMetadata]) { 
     // The current store isn't compatible with the model and should be migrated, check the version identifier of the store 

     NSManagedObjectModel *sourceManagedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil forStoreMetadata:storeMetadata]; 

     if ([[sourceManagedObjectModel versionIdentifiers] containsObject:@"Model_1_0"]) { 
      // The current version of the store is 1.0, a manual migration to 1.5 is needed in order to migrate finally to 2.0 

      NSURL *destinationModelURL = [[NSBundle mainBundle] URLForResource:@"Model.momd/Model_1_5" withExtension:@"mom"]; 
      NSManagedObjectModel *destinationManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:destinationModelURL]; 

      NSMigrationManager *migrationManager = [[NSMigrationManager alloc] initWithSourceModel:sourceManagedObjectModel destinationModel:destinationManagedObjectModel]; 
      NSMappingModel *inferredMappingModel = [NSMappingModel inferredMappingModelForSourceModel:sourceManagedObjectModel destinationModel:destinationManagedObjectModel error:&error]; 

      NSURL *destinationURL = [NSURL fileURLWithPath:[[self applicationDocumentsDirectory] stringByAppendingPathComponent:@"Migration.sqlite"]]; 

      [migrationManager migrateStoreFromURL:storeUrl 
              type:NSSQLiteStoreType 
              options:nil 
           withMappingModel:inferredMappingModel 
           toDestinationURL:destinationURL 
            destinationType:NSSQLiteStoreType 
           destinationOptions:nil 
              error:&error]; 
      if (error) { 
       DLog(@"Failed to migrate store from URL %@ with mapping model %@ to destination URL %@ with error %@", storeUrl, inferredMappingModel, destinationURL, error); 
      } 

      [[NSFileManager defaultManager] removeItemAtURL:storeUrl error:&error]; 
      [[NSFileManager defaultManager] moveItemAtURL:destinationURL toURL:storeUrl error:&error]; 
     } 
    } 

    NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption: [NSNumber numberWithBool:YES], 
           NSInferMappingModelAutomaticallyOption: [NSNumber numberWithBool:NO] }; 
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 

    if(![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) { 
     /*Error for store creation should be handled in here*/ 
     DLog(@"%@", error); 
    } 

    return persistentStoreCoordinator; 
} 
Powiązane problemy