CoreData (表结构变化处理)

引言:

Core
Data
 是 iOS 3.0
以后引入的数据持久化解决方案,其原理是对SQLite的封装,是开发者不需要接触SQL语句,就可以对数据库进行的操作.

其编码方式和原理结构方面较为特殊,本博文主要介绍在使用Core Data时遇到的各种问题以及对其核心原理进行解释.

参考资料: 

1: iOS教程:Core Data数据持久性存储基础教程

http://www.dasheyin.com/ios_jiao_cheng_core_data_shu_ju_chi_jiu_xing_cun_chu_ji_chu_jiao_cheng.html

安装:

安装的方式只有一步,引入CoreData.framework 即可.

使用:

使用Core Data起步最先要了解和熟悉的类是以下三个:

1:NSManagedObjectModel

2:NSPersistentStoreCoordinator

3:NSManagedObjectContext

在此也特别的说明一下,如果你没有理解透这三个类分别是做什么的,那么往后看到的代码都有一种非常迷茫的感觉:

接下来分别介绍每一个类的具体功能和用途:

1.NSManagedObjectModel(管理对象模型,以下简称:上下文):

构建整个数据库的表结构,表字段类型,表与表之间的关系(Relationship)等等凡是和数据结构有关的定义都通过此类来管理.

那么使用此类需要一个Data
Model
(数据模型)文件来配合其一起使用,如下图所示新建出来:

那么我们所有数据结构的定义和设计都用这个Data
Model
来完成.

在代码方面需要通过文件路径的方式找到它,并初始化NSManagedObjectModel

[csharp] view
plain
copy

  1. NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Data Model Name" withExtension:@"momd"];

  2. self.keyManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

注:新建Data
Model
文件以后的文件扩展名称是: Data Model
Name.xcdatamodeld但通过XCode编译打包成App以后,其会被转换成一个Data
Model
Name.momd文件.而我们真正要加的模型文件就是这个Data
Model
Name.momd文件.

2.NSPersistentStoreCoordinator(持久性数据协调器):

NSPersistentStoreCoordinator是真正意义上和SQLite打交道的类,主要根据NSManagedObjectModel 执行表结构的建立,通过NSManagedObjectContext 的命令执行数据交互
.

[csharp] view
plain
copy

  1. self.keyPersistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: self.keyManagedObjectModel];
  2. // handle db upgrade

  3. NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:

  4. [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,

  5. [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,

  6. nil];

  7. if (![self.keyPersistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])

  8. {}

注:通过NSManagedObjectModel初始化,一旦初始化成功,SQLite的DB,就已经有了完善的表结构关系,不过这不是我们关心的重点,继续往下.

3.NSManagedObjectContext(管理对象上下文)

NSManagedObjectContext是我们在开发中主要交互的类,数据的增删改查都通过上下文去触发命令并返回结果.
根据一个NSPersistentStoreCoordinator 完成初始化

[csharp] view
plain
copy

  1. self.keyManagedObjectContext = [[NSManagedObjectContext alloc] init];

  2. [self.keyManagedObjectContext setPersistentStoreCoordinator:self.keyPersistentStoreCoordinator];

到此,CoreData的准备工作已经完成,其实XCode已经有模版可以直接完成CoreData的准备工作,不过对于新手来说,最好还是一步一步来,加以理解,以便出现BUG时,能够及时找到解决方案,贵在理解!

接下来,开始操纵数据!

插入一条?更新一条?删除一条?

熟悉Sql语句的同学:脑子里立刻会想到:insert into table ,
 update table , delete table

那么在CoreData,这三项工作全部通过save函数来完成,一个函数完成三件事,CoreData这么犀利的?

NSPredicate(条件适配器)

NSPredicate主要为NSFetchRequest而服务,提供查询时的各种条件语句,方面过滤出复合业务需求的数据.

以下先列出 NSPredicate 支持的通配符

1:相等(==)    举例:  field ==
‘value‘

2:不相等(!=) 举例: field != ‘value‘

3:模糊(like)  举例:  field like ‘*value*‘
  或者  field like ‘?value?‘  
like  使用?表示一个字符,*表示多个字符

4:比较( > < <= >= )
举例:  field > 6

以上4种通配符都是字符串直接拼接即可,接下来的通配符在拼接字符串方面较为麻烦,但有相关代码可以辅助拼接.

5:范围(between) 举例: field between {"6", "10"}

可以通过如下代码拼接条件命令:

[csharp] view
plain
copy

  1. NSArray *range = [[NSArray alloc]initWithObjects:@"6",@"10",nil];

  2. NSPredicate *betweenPredicate =[NSPredicate predicateWithFormat:@"field between %@", range];

  3. NSLog(@"%@",betweenPredicate.predicateFormat);

6:包含(in) 举例:  filed IN
{"value1", "value2"}
可以通过如下代码拼接条件命令:

[csharp] view
plain
copy

  1. NSArray *choice = [[NSArray alloc]initWithObjects:@"value1",@"value2",nil];

  2. NSPredicate *inPredicate =[NSPredicate predicateWithFormat:@"filed in %@", choice];

  3. NSLog(@"%@",inPredicate.predicateFormat);

7:复合(or and not) 举例:
 filed == "value2" OR filed ==
"value3"

也可以通过如下代码拼接:

[csharp] view
plain
copy

  1. NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"filed == ‘value1‘  "];

  2. NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"filed == ‘value2‘ "];

  3. NSArray *predicates = [[NSArray alloc]initWithObjects:predicate1,predicate2,nil];

  4. NSPredicate *andCompoundPredicate =[NSCompoundPredicate orPredicateWithSubpredicates:predicates];

在调用save 函数时我需要注意些什么?

一个对象只属于一个上下文对象,所以不同上下文管辖的对象不允许用一个上下文来调用save
方法,这只会失败,错误提示如下:

Illegal attempt to establish a relationship ‘xyz‘ between
objects in different contexts

解决办法是(参考:StackOverflow):

[csharp] view
plain
copy

  1. NSManagedObject *book = // get a book in one MOC

  2. NSManagedObject *owner = // get an owner in a different MOC

  3. [[owner mutableSetValueForKey:@"books"] addObject:[owner managedObjectContext:objectWithID:[book objectID]]];

Persistent Store Coordinator (持久性数据协调器):
你可以将这个东西看作是数据库连接库,在这里,你将设置数据存储的名字和位置,以及数据存储的时机。
Managed Object Context
(管理数据内容):你可以将这一部分看作是数据的实际内容,这也是整个数据库中对我们而言最重要的部分(这还用说),基本上,插入数据,查询数据,删除数据的工作都在这里完成。

NSFetchRequest* request = [[NSFetchRequest alloc] init];
[request
setEntity:entity];[request
setResultType:NSManagedObjectIDResultType];
[request
setFetchBatchSize:20];
NSError* error = nil;
NSArray* items = [context
executeFetchRequest:request error:&error];
for (NSManagedObjectID*
objectID in items) {    
NSManagedObject* object = [context
objectWithID:objectID];  
  ...}

countForFetchRequest:error

1:表与表之间关系建立教程

http://blog.csdn.net/fengsh998/article/details/8123392

2:针对应用升级和表结构变动时
兼容旧版本的CoreData数据库解决办法.

遇到的问题:

当你将CoreData 加入到工程中,并启动了App一切都运行良好,

可是开发途中修改了CoreData 的 数据结构,比如添加或者删除了某个字段,或者新添加了一张表.

此时,再运行App时,发现App直接Crash.

如何解决:

这说明CoreData无法做到时时的去修改表结构,但CoreData可以以多个副本的形式来处理数据结构变化时的Crash问题.

阐述一下原理: 原理类似SVN 需要打一个 tag 一样,  一担打了Tag
就意味着这个版本的代码将不再允许修改,如果需要修改,需要到新的分枝里去实现.

当利用开发工具新建CoreData 管理文件以后:FEMicroCoopModel.xcdatamodeld 默认是只有一个分枝的.

那么添加分枝方式如下:

1.IDE->Editor->Add Model Version...

2.之后显示如下界面:

两个字段:

Version name:版本名称(按你所需来取)

Based on model:基础模型(这里选择一个,已经有的分枝,继承的概念)

Finish之后就完成了,那么新的数据结构修改,都请在这个文件上面进行操作.

当你修改的差不多以后,需要设置 CoreData管理文件的 (Versioned Core Data Model) 当前使用版本,如下图:

只有这样应用运行时才会按照新版数据结构去迁移数据和修改表结构.

代码方面只有两个地方需要注意一下:

1:添加对数据结构版本自适应的配置,代码如下:

[csharp] view
plain
copy

  1. // handle db upgrade

  2. NSDictionary *options =

  3. [NSDictionary dictionaryWithObjectsAndKeys:

  4. [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,

  5. [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,

  6. nil];



2:在实例化 NSManagedObjectModel
对象 需要传入模型名称,这里只要是你当初建立 CoreData管理对象时的名称即可.

3:让控制台拥有输出 Core Data执行的SQL语句的能力.

为Edit Scheme - Run - Arguments - 添加一项值:

[csharp] view
plain
copy

  1. -com.apple.CoreData.SQLDebug 1

如下图所示:

3:警告和错误

1:has no children

警告提示如下图:

解决方法:

将图中的勾勾去掉 编译即可

CoreData (表结构变化处理)

时间: 2024-07-28 20:21:04

CoreData (表结构变化处理)的相关文章

表结构变化

改变字段长度: ALTER table schema.table_name ALTER column_name set data type VARCHAR(10); call sysproc.admin_cmd('reorg table schema.table_name '); call sysproc.admin_cmd('runstats on table schema.table_name with distribution and indexes all'); 增加字段: ALTER

修改复制表结构

当数据库需要复制的表结构有所改变,如增加列,改变某些列的属性等表结构改变后,可以按照下列步骤执行: 1)各进程使用lag exta验证无较大延迟(秒一级即可): 2)各进程执行info exta,showch并验证ext进程重启所需日志存在: 3)按顺序停止源和目标端进程: 4)源和目标端执行修改表结构; 5)如表有主键(或唯一索引)且本次修改未修改主键,则直接重启进程: 6)但如果表无主键或者本次修改了主键(或唯一索引)则需继续执行下列步骤重建附加日志: ggsci> dblogin user

数据迁移经验总结——亿级别多表异构的数据迁移工作

由于系统改版,最近三个月在做数据迁移工作,由于业务的特殊,基本将数据迁移所能踩的坑都踩了一遍,决定好好做个总结. 迁移类型--新老系统表结构变化较大的历史数据 一.核心问题 1.新老表结构变化极大.新表是以deliver为核心,另外还涉及仓储系统的一张表,订单系统的4张表,并按照新的逻辑映射关系进行迁移. 2.增量数据迁移.在全量数据迁移时必然会有新的数据,这些数据应该实时进行迁移 3.亿级别数据性能.效率的考虑.由于订单业务非常重要,数据迁移带来的qps对数据库的压力非常大,需要不断测试迭代找

IOS CoreData的(增删查改)

(1).CoreDataa>什么是CoreDatab>CoreData增删改查 "什么时候使用COredata 什么时候使用FMDatabases"CoreData 在公司使用的比较少,用户的比较多的是FMDatabases 数据存储的结构比较简单的时候,使用CoreData 开发效率会高点,为什么?面向对象,而且不用写sql语句FMDatabases 数据结果比较复杂的时候,表与表之前的关联比较的时候 CoreData表与表之前的关联 查询分页查询模糊查询 一个数据库有一

MySQL表结构同步工具 mysql-schema-sync

mysql-schema-sync 是一款使用go开发的.跨平台的.绿色无依赖的 MySQL 表结构自动同步工具.用于将线上(其他环境)数据库结构变化同步到测试(本地)环境! 可以解决多人开发,每人都使用独立数据库导致结构不一样的问题! 支持功能:1.  同步新表2.  同步字段 变动:新增.修改3.  同步索引 变动:新增.修改4.  同步字段.索引 屏蔽变动更新5.  支持预览(只对比不同步变动)6.  邮件通知变动结果 配置 参考 默认配置文件  config.json 配置同步源.目的地

Oracle基础之分析表

analyze table tablename compute statistics; analyze index indexname compute statistics; (analyze 不会重建索引) 遇到当前表的查询或其他性能不好时,就可以对相应的表进行一次分析. 1.如果你的表经常由几千万变成几百万,又变成几千万那么需要制定分析计划定期表分析,同时可以一并分析索引,计算索引中数据的分布情况,这样CBO会选择更加准确的执行计划. 2.如果表结构变化了也要做下,也就是经常对表做dml就需

BIEE从底层表结构向上更新

影响BIEE查询结果的几个因素: 1.数据库表结构变化后,RPD如何处理? 更新物理层 增加.删除.修改表名. 添加字段:右键点击连接池,点击导入元数据.勾掉关键字,重新导入那张表. 删除字段:直接右键删除字段 修改:双击那个字段,修改表明.字段类型.字段长度. 2.RPD更新后,报表如何怎么更新? 重新加载元数据 第一种方法:在新建->分析->点击刷新->重新导入元数据 第二种方法:管理->维护和故障排除->重新加载文件和元数据 解释: 在BIEE admin tools中

oracle查询某张表某个时间点的数据(表结构未改变前)

原文地址--http://blog.csdn.net/qq525099302/article/details/47253641 SELECT * FROM b_role_authority as of timestamp to_timestamp('2015-07-25','yyyy-mm-dd') 注意:表结构变化过后无效,只能查询到一段时间内的记录 版权声明:本文为博主原创文章,未经博主允许不得转载.

Django(三) ORM 数据库操作

比较有用 转自 http://blog.csdn.net/fgf00/article/details/53678205 一.DjangoORM 创建基本类型及生成数据库表结构 1.简介 2.创建数据库 表结构 二.Django ORM基本增删改查 1.表数据增删改查 2.表结构修改 三.Django ORM 字段类型 1.字段类型介绍 2.字段参数介绍 3.Django ORM 外键操作 一.DjangoORM 创建基本类型及生成数据库表结构 1.简介 ORM:关系对象映射.定义一个类自动生成数