2013-02-26 35 views
9

Tôi đang cố thực hiện di chuyển Dữ liệu lõi iOS yêu cầu MappingModel. Dữ liệu cốt lõi không thể sử dụng mô hình ánh xạ vì một lý do nào đó và nó quay trở lại một quá trình di chuyển nhẹ tự động.Không tìm thấy mô hình ánh xạ phù hợp để di chuyển dữ liệu lõi

Tôi đã bật tùy chọn MigrationDebug để nhận thêm thông tin và những gì tôi thấy không có ý nghĩa. Hàm băm nguồn và đích của mô hình ánh xạ giống hệt nhau, bỏ qua thứ tự, đến các đối tượng ManagedObjectModels nguồn và đích. Có vẻ như mô hình lập bản đồ nên được sử dụng nhưng nhật ký cho biết "không tìm thấy mô hình ánh xạ phù hợp".

Đây là (elided) 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: ... 

Trả lời

8

Mô hình ánh xạ được tạo bởi Xcode 4 không tạo ra băm chính xác cần thiết để di chuyển xảy ra. Bạn có thể so sánh đầu ra từ nhật ký di chuyển với các tệp băm của tệp ánh xạ của mình bằng mã bên dưới:

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); 
    } 

Bạn sẽ thấy rằng chúng không khớp với dấu băm trong đầu ra nhật ký di chuyển.

Giải pháp thay thế là tạo tệp ánh xạ trong Xcode 5.

+0

Vì vậy, chúng tôi không thể sử dụng công cụ di chuyển trong Xcode 4.6.2, vì nó tạo ra tệp sai? –

+2

Tôi không biết nếu đây là giải pháp, nhưng nó chắc chắn là một giải pháp. Sử dụng tập tin được tạo bởi Xcode 5 DP4 làm việc cho tôi. –

+1

Đối với Xcode 4, hãy thử [câu trả lời này] (http://stackoverflow.com/a/9428260/1402846). – Pang

0

Mô hình bản đồ có lẽ là không đủ để xử lý sự di cư. Trong trường hợp này, mô hình ánh xạ sẽ không được tải, ngay cả khi nó khớp với mô hình nguồn và đích.

Viết thử nghiệm để di chuyển. Làm lại các thay đổi đối với mô hình của bạn từng bước và kiểm tra quá trình di chuyển. Bằng cách đó bạn sẽ tìm thấy thay đổi ngăn chặn mô hình ánh xạ tải.

Lookout for: Đổi tên thuộc tính hoặc tạo thuộc tính mà không chỉ định giá trị mặc định. Thay đổi các thuộc tính thành không bắt buộc.

Trong những trường hợp đó, bạn phải chỉ định hành vi theo cách thủ công trong mô hình ánh xạ.

+0

Tôi gặp vấn đề tương tự và mặc dù tôi đã viết lại mô hình ánh xạ từ đầu tôi vẫn không thể làm việc. Việc di chuyển không thành vấn đề gì tôi thử. – s1m0n

0

Có cùng vấn đề. Tôi đã xóa một thực thể và đổi tên các trường mối quan hệ tương ứng. Trước tiên, tôi đã cố gắng sử dụng di chuyển nhẹ và do đó được chỉ định ID đổi tên cho các mối quan hệ. Do sự giám sát, tôi trộn các trường được sử dụng cho "ID đổi tên" và "Công cụ sửa đổi băm". Sau khi sửa chữa tất cả mọi thứ hoạt động như mong đợi.

3

Trong phương pháp persistentStoreCoordinator của bạn cung cấp cho dòng mã này

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

Nếu doesnt giúp đỡ này thì bạn cần phải đi cho người sử dụng thực hiện chuyển đổi. Vì vậy, bạn sẽ phải tạo một mô hình ánh xạ bằng cách sử dụng mô hình nguồn và đích. Trong trường hợp thiết lập,

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

Tạo metadata Douce với mã sau đây

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]); 
    } 

và thực hiện các chức năng sau

- (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

Sau khi điều tra thêm tác tôi phát hiện ra tôi đã gặp vấn đề tương tự như đã đề cập ở đây (Core Data migration fails for to-one relationship). Cài đặt mức tối thiểu là 1 thay vì không có tối thiểu trong mối quan hệ của tôi, Dữ liệu cốt lõi sử dụng mô hình ánh xạ tùy chỉnh của tôi. Mặc dù tôi không chắc rằng tôi cho rằng đây là lỗi trong Dữ liệu cốt lõi.
Tuy nhiên, điều này đòi hỏi tôi phải thay đổi mô hình ánh xạ ban đầu (1.0) (mà người dùng cũng đã sử dụng). Khắc phục mà tôi đưa ra là tạo một mô hình ánh xạ mới giữa 1.0 và 2.0 có tên là 1.5. Điều duy nhất khác với 1.5 so với 1.0 là mức tối thiểu của mối quan hệ, nằm trong khoảng 1.5 được đặt thành 1. Bây giờ, tôi có thể cho phép Dữ liệu cốt lõi thực hiện di chuyển nhẹ từ 1,0 đến 1,5 và sau đó thực hiện di chuyển tùy chỉnh của riêng tôi từ 1,5 đến 2,0. Mặc dù nó có thể là một giải pháp hacky, nó hoạt động hoàn hảo.Tôi đã dán mã xử lý việc di chuyển bên dưới.

- (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; 
} 
Các vấn đề liên quan