核心数据迁移“无法合并具有两个名为“foo”的不同实体的模型”

发布于 2024-09-24 17:08:42 字数 1843 浏览 1 评论 0原文

我知道这是一个常见问题,但是我找到的解决方案似乎都不适合我。

这是我的情况: 我的应用程序有一个数据模型,我想为其添加版本控制。所以在XCode中,我做了Design ->数据模型->添加模型版本。我还更新了我的委托的 persistenceStoreCoordinator 方法,如下所示:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }
    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory]
                                               stringByAppendingPathComponent: @"foo.sqlite"]];

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
                             nil];
    NSError *error = nil;
    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*/
    }

    return persistentStoreCoordinator;
}

为了确保一切仍然正常工作,我进行了全部清理、构建并在模拟器中对其进行了测试。到目前为止一切正常。

接下来,我选择了新版本数据模型,使用 XCode 将其设置为当前版本,并向实体添加了一个额外属性。然后我做了一个干净的一切,构建。现在,每当我启动应用程序时,它就会崩溃并出现以下错误:“无法将模型与名为“foo”的两个不同实体合并”。

我做错了什么?我尝试确保没有数据模型添加到目标,仅将当前版本的数据模型添加到目标,以及两者。每次测试时我都会确保清理所有内容。

谁能解释一下为什么它对我不起作用?

编辑:

这是我的 ManagedObjectModel 方法:

- (NSManagedObjectModel *)managedObjectModel {
  if (managedObjectModel != nil) {
    return managedObjectModel;
  }
  managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];

  return managedObjectModel;
}

I know this is a frequently asked question, however none of the solutions that I have found seem to work for me.

This is my situation:
I have one data model for my application, and I wanted to add versioning to it. So in XCode, I did Design -> Data Model -> Add Model Version. I also updated my delegate's persistentStoreCoordinator method to look like this:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }
    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory]
                                               stringByAppendingPathComponent: @"foo.sqlite"]];

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
                             nil];
    NSError *error = nil;
    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*/
    }

    return persistentStoreCoordinator;
}

Just to make sure everything was still working, I did a clean all, build, and tested it in the simulator. Everything worked so far.

Next I chose the new version data model, set it to be the current version using XCode, and added one extra attribute to an entity. I then did a clean all, build. And now whenever I start the application it crashes with this error: 'Can't merge models with two different entities named 'foo''.

What am I doing wrong? I have tried making sure that no data model is added to the target, adding just the current version data model to the target, and both. Every time I test I make sure to clean all.

Can anyone shed some light as to why it does not work for me?

EDIT:

here is my managedObjectModel method:

- (NSManagedObjectModel *)managedObjectModel {
  if (managedObjectModel != nil) {
    return managedObjectModel;
  }
  managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];

  return managedObjectModel;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

余生一个溪 2024-10-01 17:08:42

我已经预料到了 ManagedObjectModel getter 的实现。

在您的实现中,捆绑包中的所有模型都将合并为一个模型。因此,.momd 中的所有版本也会合并,从而导致重复的实体定义。

更改代码以使用适当的模型文件显式初始化模型,它应该可以正常工作。

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"datamodel" ofType:@"momd"];
NSURL *modelURL = [NSURL fileURLWithPath:modelPath];
managedObjectModel_ = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];    

I already expected this implementation of the managedObjectModel getter.

In your implementation all models within the bundle are merged into one single model. Therefore also all versions within the .momd are merged resulting in duplicate entity definitions.

Change the code to explicitly initialize the model with the apropriate model file and it should work fine.

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"datamodel" ofType:@"momd"];
NSURL *modelURL = [NSURL fileURLWithPath:modelPath];
managedObjectModel_ = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];    
木有鱼丸 2024-10-01 17:08:42

如果您在核心数据上使用版本模型,则始终必须初始化为您要使用的模型版本。在Application Bundle 上,您将找到一个扩展名为.momd 的文件,该文件是完整模型。在此文件中,您会发现许多 .mom 文件,每个 .mom 文件代表模型的一个版本

如果您运行应用程序并使用 .momd 文件和其中的所有版本进行初始化,Core Data 将创建所有版本,稍后我们将出现“重复实体” 错误,Core数据不知道用什么版本。现在,解决问题的唯一方法是删除应用程序,将代码指向正确的 .mom 文件并再次运行,这样 Core Data 仅创建一个版本的内部数据库。

这是完成这项工作的一段代码:

NSString *fullModelName    = @"myModel.momd";    // The name of the main model.
NSString *modelVersionName = @"myModel1.0.mom";  // Only the name of the version.
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSString *modelPath = [NSString stringWithFormat:@"%@/%@/%@", bundlePath, fullModelName,  modelVersionName];
//
NSURL *modelURL = [NSURL fileURLWithPath:modelPath];
managedObjectModel_ = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 

If you're using Version Models on Core Data you always have to initialize to the version of the model that you want to use. On the Application Bundle you will find one file with extension .momd that is the Full Model. Inside of this file you will find a lot of .mom files inside, each .mom file represent one version of your model.

If you run your application and initialize with the .momd file and all versions inside, Core Data will create all versions and later we will have the "duplicated entity" error, Core Data don't known what version use. Now, the only way to fix the problem is delete the app, point your code to the correct .mom file and run again, so Core Data create only one version of the internal database.

Here's one snippet of code that do the job:

NSString *fullModelName    = @"myModel.momd";    // The name of the main model.
NSString *modelVersionName = @"myModel1.0.mom";  // Only the name of the version.
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSString *modelPath = [NSString stringWithFormat:@"%@/%@/%@", bundlePath, fullModelName,  modelVersionName];
//
NSURL *modelURL = [NSURL fileURLWithPath:modelPath];
managedObjectModel_ = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文