参考文章:http://blog.slalom.com/2010/01/08/splitting-an-entity-in-a-coredata-migration/
最近自己做的背单词软件,在之前的设计上有一个非常大的缺陷就是把单词读音的语音文件放在数据库里面了,而且作为word表里面的一个字段储存。一开始测试的时候没有什么大问题,但是单词越来越多之后查询就变得非常之慢。后面自己加上的一些功能都要频繁地对比数据库,所以做了一个优化就是在core data fetch request里面指定要获取的字段,在这里排除读音字段的话,查询就非常快了,尤其当我把单词本身的string做了index之后。但是代码就很难看了。
core data里面的讲到类似情况的优化时说,需要把大数据文件新建一个Entity独立出来,然后和以前的Entity建立一对一关系。然而"Core Data Model Versioning and Data Migration Programming"这篇文档完全忽略了怎么样拆分Entity这块内容,今天搜到了一篇文章才知道怎么做。
以下就是一个示范,基于Xcode生成的core data模板程序,并且我假定你已经知道最基本的Model versioning和mapping object的知识。
原始的Model是这样的:
假设我们现在的目标是把address分离到一个独立的entity中去。
现在新建立一个Model Version,假设命名为version2,把它搞成这样:
这样,就把address分离出去了。
接下来要做Migration了,新建一个Mapping Model文件:
根据向导,将source设置为原始的Model文件,target设置为新的Model文件。然后Xcode会生成如下的Mapping文件:
在这个文件基础上,我们只要稍作修改就能完成了。
首先把ENTITY MAPPING下面的Address重命名为EventToAddress(这步可做可不做),然后在右边栏中的Entity Mapping中,设置Source为Event:
接下来改address的Value Expression为$source.address 如下:
然后在左边的ENTITY MAPPINGS栏中切换到EventToEvent,选中Relation Mappings中的address,在右边栏中设置Key Path为$source,设置Mapping Name为EventToAddress(如果刚才没改名,就用刚才的名字)。
然后设置model的current version为version2:
最后一步,在程序中初始化NSPersistentStoreCoordinator的地方,加上NSMigratePersistentStoresAutomaticallyOption的选项,代码类似如下:
1
2
3
4
5
6
7
8
|
_persistentStoreCoordinator
= [[ NSPersistentStoreCoordinator
alloc] initWithManagedObjectModel:[ self
managedObjectModel]]; NSDictionary
*options = [ NSDictionary
dictionaryWithObjectsAndKeys: [ NSNumber
numberWithBool: YES ],
NSMigratePersistentStoresAutomaticallyOption , [ NSNumber
numberWithBool: YES ],
NSInferMappingModelAutomaticallyOption ,
nil ]; if
(![_persistentStoreCoordinator addPersistentStoreWithType: NSSQLiteStoreType
configuration: nil
URL:storeURL options:options error:&error]) { NSLog (@ "Unresolved
error %@, %@" ,
error, [error userInfo]); abort(); } |
最后,运行程序,在程序初始化的时候,就会自动做migration了。如果要migration的数据量非常大,就会非常的慢。
完整源代码见:https://gitcafe.com/hikui/iOS-Example/tree/master/CoreDataMigrationDemo