当我更新我的sqlite核心数据存储时,如何避免在SQL执行期间出现"错误:约束失败"?

Sim*_*mon 8 iphone core-data objective-c

我们的应用程序允许用户从API提供的列表中选择位置.该列表不经常更新,只能通过添加项目进行更新,因此应用程序每次都会在Core Data sqlite商店中附带快照而不是点击API,我们希望它定期更新列表.这样做的代码是这样的:

  • 为线程创建托管对象上下文
  • 从API获取完整列表
  • 每一个人:
    • 在上下文中找到匹配的locationID的位置
    • 如果找不到,请在上下文中插入一个新的
    • 使用新信息更新位置
  • 保存上下文

从空白DB开始时,这很好.但是,当我们第二次运行它时,它在保存期间失败并显示消息"SQL执行期间出错:约束失败".即使我将它限制在一个位置,它也会这样做.如果我打开SQL调试,我会看到以下内容:

CoreData: sql: BEGIN EXCLUSIVE
CoreData: sql: COMMIT
CoreData: sql: BEGIN EXCLUSIVE
CoreData: sql: INSERT INTO ZLOCATION(Z_PK, Z_ENT, Z_OPT, ZGEOID, ZCOUNTY, ZCOUNTRYCODE, ZNAME, ZLATITUDE, ZLONGITUDE, ZLANGUAGECODE) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
CoreData: error: (19) constraint failed
CoreData: annotation: Disconnecting from sqlite database due to an error.
Run Code Online (Sandbox Code Playgroud)

然后重新连接并再次尝试几次,然后放弃.

我的代码肯定是找到旧的Locations并且对象都是有效的 - 或者至少[object validateForUpdate]返回YES.错误是什么意思?有没有办法找出哪个约束失败?

如果我使用二进制存储,则错误消失 - 但二进制存储是原子的并且在写入时会阻塞多年.它看起来像sqlite商店中的一个错误 - 有没有人找到解决方法?

Sim*_*mon 6

我注意到它INSERT INTO ZLOCATION没有UPDATE ZLOCATION,所以我看了一下我将位置插入上下文的位置.我有:

if ([object isInserted])
{
    if (![object validateForUpdate:&error])
    {
        NSLog(@"Invalid object %@: %@, %@", object, error, [error userInfo]);   
        break;
    }
}
else
{
    if ([object validateForInsert:&error])
    {
        [context insertObject:object];
    }
    else
    {
        NSLog(@"Invalid object %@: %@, %@", object, error, [error userInfo]);   
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

我不知道的是,对于来自数据库的对象,它[object isInserted]是错误的.所以,我插入一个已经插入的对象,结果就崩溃了.当我将其更改为[object managedObjectContext]时,我的问题就消失了.