我们的应用程序允许用户从 API 提供的列表中选择一个位置。该列表不经常更新,并且仅通过添加项目进行更新,因此应用程序不会每次都访问 API,而是在 Core Data sqlite 存储中附带一个快照,我们希望它定期更新列表。这样做的代码如下:
- 为线程创建一个托管对象上下文
- 从 API 获取完整列表
- 每一个:
- 在上下文中找到具有匹配 locationID 的 Location
- 如果没有找到,则在上下文中插入一个新的
- 用新信息更新位置
- 保存上下文
当从空白数据库开始时,这工作正常。但是,当我们第二次运行它时,它在保存期间失败并显示消息“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.
然后它会重新连接并在放弃之前重试几次。
我的代码肯定会找到旧位置并且对象都是有效的 - 或者至少 [object validateForUpdate] 返回 YES。错误是什么意思?有没有办法找出哪个约束失败了?
如果我使用二进制存储,错误就会消失 - 但二进制存储是原子的,并且在写入时会阻塞很长时间。它看起来像是 sqlite 存储中的错误 - 有没有人找到解决方法?
最佳答案
我注意到它正在执行 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;
}
}
我不知道的是,对于从数据库中出来的对象,[object isInserted]
是 false。所以,我插入了一个已经插入的对象,结果它崩溃了。当我将其更改为 [object managedObjectContext] 时,我的问题就消失了。
关于iphone - 当我更新我的 sqlite 核心数据存储时,如何避免获得 "error during SQL execution : constraint failed"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7385011/