使用父实体集保存核心数据

Ser*_* Jr 5 sqlite core-data ios ios9

在我的应用程序中,我有可以存储一些可选数据的对象.有两种类型的此类对象 - 例如,它们应该是唯一的,并且不需要是唯一的.

那些独特的属性还有额外的属性 - uuid - 通过它来检查唯一性.

调用非唯一,例如StoreObject和唯一的UniqueStoreObject.除了那个uuid属性,它们完全相同.

因此,StoreObject是没有父实体的实体.UniqueStoreObject是父实体设置为StoreObject的实体.正如我所说 - 两个实体描述的对象可以在一个后端同时满足.

但是,如果我尝试保存NSManagedContext,其中我有StoreObject对象,我从Core Data获取保存错误日志消息 -

CoreData: error: (1) I/O error for database at *path to base*/MapStorageTest.sqlite. SQLite error code:1, 'near "WHERE": syntax error'
Core Data: error: -executeRequest: encountered exception = I/O error for database at *path to base*/MapStorageTest.sqlite.  SQLite error code:1, 'near "WHERE": syntax error' with userInfo = {
NSFilePath = "*path to base*/MapStorageTest.sqlite";
NSSQLiteErrorDomain = 1;
}
Run Code Online (Sandbox Code Playgroud)

为了使陌生人,这种行为不稳定.如果它出现一次 - 它将出现在下一次应用程序启动时.但是,如果我,例如,删除uniquing字段,或其他一些Entity(这里没有提到两个),或重新创建其中一个实体(删除它并在Xcode托管模型工具中重新编写),它就会消失.

无法找到与字段的可选性或托管对象工具中的唯一约束无关的内容.我只能捕获一件事 - 这个StoreObject实体必须具有子实体,并在保存之前直接在上下文中实例化.

当我为没有属性的非唯一商店创建单独的实体并且是StoreObject实体的子代时 - 问题就消失了

更新

在评论中已经要求代码示例.即使是最简单的情况也可能导致这个错误

 //Everything happens in viewDidLoad method

//Context is created by Xcode-genereate code. It has main queue concurency type
NSManagedObjectContext *ctx = [(AppDelegate*)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSManagedObject *storeObject = [NSEntityDescription insertNewObjectForEntityForName:@"StoreObject" 
                                                             inManagedObjectContext:ctx];
[ctx save:&err]; //Here I get those error messages and error object is returned 
Run Code Online (Sandbox Code Playgroud)

更新2

这是我用SQLDebug参数1得到的

2016-02-25 22:59:05.438 ParentEntityCheck[31701:11387091] CoreData: annotation: Connecting to sqlite database file at "*path to base*/ParentEntityCheck.sqlite"
2016-02-25 22:59:05.441 ParentEntityCheck[31701:11387091] CoreData: annotation: creating schema.
2016-02-25 22:59:05.441 ParentEntityCheck[31701:11387091] CoreData: sql: pragma page_size=4096
2016-02-25 22:59:05.441 ParentEntityCheck[31701:11387091] CoreData: sql: pragma auto_vacuum=2
2016-02-25 22:59:05.445 ParentEntityCheck[31701:11387091] CoreData: sql: BEGIN EXCLUSIVE
2016-02-25 22:59:05.445 ParentEntityCheck[31701:11387091] CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_METADATA'
2016-02-25 22:59:05.446 ParentEntityCheck[31701:11387091] CoreData: sql: CREATE TABLE ZSTOREOBJECT ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZLASTLOAD TIMESTAMP, ZSTORECAPACITY VARCHAR, ZSTORENAME VARCHAR, ZUUID VARCHAR UNIQUE ) 
2016-02-25 22:59:05.447 ParentEntityCheck[31701:11387091] CoreData: sql: CREATE INDEX IF NOT EXISTS ZSTOREOBJECT_Z_ENT_INDEX ON ZSTOREOBJECT (Z_ENT)
2016-02-25 22:59:05.447 ParentEntityCheck[31701:11387091] CoreData: annotation: Creating primary key table.
2016-02-25 22:59:05.448 ParentEntityCheck[31701:11387091] CoreData: sql: CREATE TABLE Z_PRIMARYKEY (Z_ENT INTEGER PRIMARY KEY, Z_NAME VARCHAR, Z_SUPER INTEGER, Z_MAX INTEGER)
2016-02-25 22:59:05.448 ParentEntityCheck[31701:11387091] CoreData: sql: INSERT INTO Z_PRIMARYKEY(Z_ENT, Z_NAME, Z_SUPER, Z_MAX) VALUES(1, 'StoreObject', 0, 0)
2016-02-25 22:59:05.449 ParentEntityCheck[31701:11387091] CoreData: sql: INSERT INTO Z_PRIMARYKEY(Z_ENT, Z_NAME, Z_SUPER, Z_MAX) VALUES(2, 'UniqueStoreObject', 1, 0)
2016-02-25 22:59:05.449 ParentEntityCheck[31701:11387091] CoreData: sql: CREATE TABLE Z_METADATA (Z_VERSION INTEGER PRIMARY KEY, Z_UUID VARCHAR(255), Z_PLIST BLOB)
2016-02-25 22:59:05.450 ParentEntityCheck[31701:11387091] CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_METADATA'
2016-02-25 22:59:05.450 ParentEntityCheck[31701:11387091] CoreData: sql: DELETE FROM Z_METADATA WHERE Z_VERSION = ?
2016-02-25 22:59:05.450 ParentEntityCheck[31701:11387091] CoreData: sql: INSERT INTO Z_METADATA (Z_VERSION, Z_UUID, Z_PLIST) VALUES (?, ?, ?)
2016-02-25 22:59:05.451 ParentEntityCheck[31701:11387091] CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_MODELCACHE'
2016-02-25 22:59:05.451 ParentEntityCheck[31701:11387091] CoreData: sql: CREATE TABLE Z_MODELCACHE (Z_CONTENT BLOB)
2016-02-25 22:59:05.454 ParentEntityCheck[31701:11387091] CoreData: sql: INSERT INTO Z_MODELCACHE (Z_CONTENT) VALUES (?)
2016-02-25 22:59:05.454 ParentEntityCheck[31701:11387091] CoreData: sql: COMMIT
2016-02-25 22:59:05.455 ParentEntityCheck[31701:11387091] CoreData: sql: pragma journal_mode=wal
2016-02-25 22:59:05.457 ParentEntityCheck[31701:11387091] CoreData: sql: pragma journal_mode=wal
2016-02-25 22:59:05.457 ParentEntityCheck[31701:11387091] CoreData: sql: pragma cache_size=200
2016-02-25 22:59:05.458 ParentEntityCheck[31701:11387091] CoreData: sql: SELECT Z_VERSION, Z_UUID, Z_PLIST FROM Z_METADATA
2016-02-25 22:59:05.459 ParentEntityCheck[31701:11387091] CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_MODELCACHE'
2016-02-25 22:59:05.462 ParentEntityCheck[31701:11387091] CoreData: sql: BEGIN EXCLUSIVE
2016-02-25 22:59:05.463 ParentEntityCheck[31701:11387091] CoreData: sql: SELECT Z_MAX FROM Z_PRIMARYKEY WHERE Z_ENT = ?
2016-02-25 22:59:05.463 ParentEntityCheck[31701:11387091] CoreData: sql: UPDATE Z_PRIMARYKEY SET Z_MAX = ? WHERE Z_ENT = ? AND Z_MAX = ?
2016-02-25 22:59:05.464 ParentEntityCheck[31701:11387091] CoreData: sql: COMMIT
2016-02-25 22:59:05.465 ParentEntityCheck[31701:11387091] CoreData: sql: BEGIN EXCLUSIVE
2016-02-25 22:59:05.466 ParentEntityCheck[31701:11387091] CoreData: sql: INSERT INTO ZSTOREOBJECT(Z_PK, Z_ENT, Z_OPT, ZLASTLOAD, ZSTORECAPACITY, ZSTORENAME) VALUES(?, ?, ?, ?, ?, ?)
2016-02-25 22:59:05.467 ParentEntityCheck[31701:11387091] CoreData: sql: UPDATE ZSTOREOBJECT SET  WHERE Z_PK = ?
2016-02-25 22:59:05.467 ParentEntityCheck[31701:11387091] CoreData: annotation: Disconnecting from sqlite database due to an error.
2016-02-25 22:59:05.469 ParentEntityCheck[31701:11387091] CoreData: error: (1) I/O error for database at *path to base*/ParentEntityCheck.sqlite.  SQLite error code:1, 'near "WHERE": syntax error'
2016-02-25 22:59:05.470 ParentEntityCheck[31701:11387091] Core Data: error: -executeRequest: encountered exception = I/O error for database at *path to base*/ParentEntityCheck.sqlite.  SQLite error code:1, 'near "WHERE": syntax error' with userInfo = {
    NSFilePath = "*path to base*/ParentEntityCheck.sqlite";
    NSSQLiteErrorDomain = 1;
}
2016-02-25 22:59:05.471 ParentEntityCheck[31701:11387091] CoreData: annotation: Connecting to sqlite database file at "*path to base*/ParentEntityCheck.sqlite"
2016-02-25 22:59:05.471 ParentEntityCheck[31701:11387091] CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_METADATA'
2016-02-25 22:59:05.473 ParentEntityCheck[31701:11387091] CoreData: sql: pragma journal_mode=wal
2016-02-25 22:59:05.473 ParentEntityCheck[31701:11387091] CoreData: sql: pragma cache_size=200
2016-02-25 22:59:05.474 ParentEntityCheck[31701:11387091] CoreData: sql: BEGIN EXCLUSIVE
2016-02-25 22:59:05.474 ParentEntityCheck[31701:11387091] CoreData: sql: INSERT INTO ZSTOREOBJECT(Z_PK, Z_ENT, Z_OPT, ZLASTLOAD, ZSTORECAPACITY, ZSTORENAME) VALUES(?, ?, ?, ?, ?, ?)
2016-02-25 22:59:05.475 ParentEntityCheck[31701:11387091] CoreData: sql: UPDATE ZSTOREOBJECT SET  WHERE Z_PK = ?
2016-02-25 22:59:05.475 ParentEntityCheck[31701:11387091] CoreData: annotation: Disconnecting from sqlite database due to an error.
2016-02-25 22:59:05.477 ParentEntityCheck[31701:11387091] CoreData: error: (1) I/O error for database at *path to base*/ParentEntityCheck.sqlite.  SQLite error code:1, 'near "WHERE": syntax error'
2016-02-25 22:59:05.477 ParentEntityCheck[31701:11387091] Core Data: error: -executeRequest: encountered exception = I/O error for database at *path to base*/ParentEntityCheck.sqlite.  SQLite error code:1, 'near "WHERE": syntax error' with userInfo = {
    NSFilePath = "*path to base*/ParentEntityCheck.sqlite";
    NSSQLiteErrorDomain = 1;
}
2016-02-25 22:59:05.488 ParentEntityCheck[31701:11387091] CoreData: annotation: Connecting to sqlite database file at "*path to base*/ParentEntityCheck.sqlite"
2016-02-25 22:59:05.489 ParentEntityCheck[31701:11387091] CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_METADATA'
2016-02-25 22:59:05.491 ParentEntityCheck[31701:11387091] CoreData: sql: pragma journal_mode=wal
2016-02-25 22:59:05.491 ParentEntityCheck[31701:11387091] CoreData: sql: pragma cache_size=200
2016-02-25 22:59:05.491 ParentEntityCheck[31701:11387091] CoreData: sql: BEGIN EXCLUSIVE
2016-02-25 22:59:05.492 ParentEntityCheck[31701:11387091] CoreData: sql: INSERT INTO ZSTOREOBJECT(Z_PK, Z_ENT, Z_OPT, ZLASTLOAD, ZSTORECAPACITY, ZSTORENAME) VALUES(?, ?, ?, ?, ?, ?)
2016-02-25 22:59:05.492 ParentEntityCheck[31701:11387091] CoreData: sql: UPDATE ZSTOREOBJECT SET  WHERE Z_PK = ?
2016-02-25 22:59:05.493 ParentEntityCheck[31701:11387091] CoreData: annotation: Disconnecting from sqlite database due to an error.
2016-02-25 22:59:05.495 ParentEntityCheck[31701:11387091] CoreData: error: (1) I/O error for database at *path to base*/ParentEntityCheck.sqlite.  SQLite error code:1, 'near "WHERE": syntax error'
2016-02-25 22:59:05.496 ParentEntityCheck[31701:11387091] Core Data: error: -executeRequest: encountered exception = I/O error for database at *path to base*/ParentEntityCheck.sqlite.  SQLite error code:1, 'near "WHERE": syntax error' with userInfo = {
    NSFilePath = "*path to base*/ParentEntityCheck.sqlite";
    NSSQLiteErrorDomain = 1;
}
2016-02-25 22:59:05.560 ParentEntityCheck[31701:11387091] CoreData: annotation: Connecting to sqlite database file at "*path to base*/ParentEntityCheck.sqlite"
2016-02-25 22:59:05.561 ParentEntityCheck[31701:11387091] CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_METADATA'
2016-02-25 22:59:05.562 ParentEntityCheck[31701:11387091] CoreData: sql: pragma journal_mode=wal
2016-02-25 22:59:05.562 ParentEntityCheck[31701:11387091] CoreData: sql: pragma cache_size=200
2016-02-25 22:59:05.562 ParentEntityCheck[31701:11387091] CoreData: sql: BEGIN EXCLUSIVE
2016-02-25 22:59:05.563 ParentEntityCheck[31701:11387091] CoreData: sql: INSERT INTO ZSTOREOBJECT(Z_PK, Z_ENT, Z_OPT, ZLASTLOAD, ZSTORECAPACITY, ZSTORENAME) VALUES(?, ?, ?, ?, ?, ?)
2016-02-25 22:59:05.600 ParentEntityCheck[31701:11387091] CoreData: sql: UPDATE ZSTOREOBJECT SET  WHERE Z_PK = ?
2016-02-25 22:59:05.601 ParentEntityCheck[31701:11387091] CoreData: annotation: Disconnecting from sqlite database due to an error.
2016-02-25 22:59:05.602 ParentEntityCheck[31701:11387091] CoreData: error: (1) I/O error for database at *path to base*/ParentEntityCheck.sqlite.  SQLite error code:1, 'near "WHERE": syntax error'
2016-02-25 22:59:05.683 ParentEntityCheck[31701:11387091] Error saving ctx Error Domain=NSCocoaErrorDomain Code=256 "The file “ParentEntityCheck.sqlite” couldn’t be opened." UserInfo={NSFilePath=*path to base*/ParentEntityCheck.sqlite, NSSQLiteErrorDomain=1, NSUnderlyingException=I/O error for database at *path to base*/ParentEntityCheck.sqlite.  SQLite error code:1, 'near "WHERE": syntax error'}
Run Code Online (Sandbox Code Playgroud)

pba*_*sdf 4

我认为存在两个重叠的问题:主要问题是 的唯一性约束uuid。我尝试创建与您自己的类似的设置,并且我可以重现错误的唯一情况是如果uuid有唯一性约束

我从你的问题中注意到,你不相信存在唯一性约束,但我认为这是由于第二个问题:最初我很困惑,因为我尝试应用唯一性约束是行不通的。uuid而您的 SQLDebug在构建数据库时显示了一个 UNIQUE 属性:

CoreData: sql: CREATE TABLE ZSTOREOBJECT ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZLASTLOAD TIMESTAMP, ZSTORECAPACITY VARCHAR, ZSTORENAME VARCHAR, ZUUID VARCHAR UNIQUE )
Run Code Online (Sandbox Code Playgroud)

我的没有。经过清理和一些实验后,我终于得到了唯一性约束(在上述意义上)。一旦我这样做了,我就开始遇到和你一样的错误:

CoreData: sql: UPDATE ZSTOREOBJECT SET  WHERE Z_PK = ?
CoreData: annotation: Disconnecting from sqlite database due to an error.
CoreData: error: (1) I/O error for database at *path to base*/ParentEntityCheck.sqlite.  SQLite error code:1, 'near "WHERE": syntax error'
Run Code Online (Sandbox Code Playgroud)

然后我尝试消除约束。

在此输入图像描述

问题仍然存在。即使我清理了构建,从模拟器中删除了应用程序并重新运行:还是发生了同样的问题。不知何故,尽管数据模型编辑器显示对 uuid 没有限制,但仍应用了一个限制。我查看了 xcdatamodeld 中隐藏的 XML,它是:

<entity name="UniqueStoreObject" representedClassName="UniqueStoreObject" parentEntity="StoreObject" syncable="YES">
    <attribute name="uuid" attributeType="String" syncable="YES"/>
    <uniquenessConstraints>
        <uniquenessConstraint>
            <constraint value="uuid"/>
        </uniquenessConstraint>
    </uniquenessConstraints>
</entity>
Run Code Online (Sandbox Code Playgroud)

显然,Xcode 只是没有更新模型来反映添加/删除的唯一性约束。但是,如果您对模型进行其他更改(例如,添加和删除属性),则会对唯一性约束进行更改,并且uuid在创建表时应用 UNIQUE 定义,并且错误会消失。

这与您自己的观察是一致的:

但是,例如,如果我删除唯一字段或其他一些实体(此处未提及两个),或重新创建其中一个实体(删除它并在 Xcode 托管模型工具中重新编写),它可能会消失。

您对模型中其他实体或属性所做的更改会导致对唯一性约束的任何更改生效。

一旦您使用 Xcode 解决了这个问题,主要问题就变得更加清晰:唯一性约束似乎不适用于子实体

所有这些都是解释而不是解决方案。我猜想您的UniqueStoreObject子类有一些特定的代码,而不是使用 CoreData 唯一性约束。我希望我有一个更好的解决方案,但我希望你能睡得更好一点......