2016-02-22 17 views
5

Trong ứng dụng của tôi, tôi có các đối tượng có thể lưu trữ một số dữ liệu tùy chọn. Có hai loại đối tượng như vậy - đó là duy nhất và như vậy, không cần phải là duy nhất.Lưu dữ liệu chính với bộ thực thể gốc

Đó là số duy nhất có thuộc tính bổ sung - uuid - để kiểm tra tính duy nhất.

Không độc đáo được gọi, ví dụ StoreObject và UniqueStoreObject duy nhất. Ngoại trừ thuộc tính đó uuid chúng hoàn toàn giống nhau.

Vì vậy, StoreObject là thực thể không có thực thể mẹ. UniqueStoreObject là thực thể với thực thể cha được đặt thành StoreObject. Như tôi đã nói - các đối tượng được mô tả bởi cả hai thực thể có thể được đáp ứng đồng thời trong một chương trình phụ trợ.

Nhưng, nếu tôi cố gắng tiết kiệm NSManagedContext, trong đó tôi có các đối tượng StoreObject, tôi nhận được lưu tin nhắn log lỗi từ 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; 
} 

Để làm lạ, hành vi này là không ổn định. Nếu nó xuất hiện một lần - nó sẽ xuất hiện trong lần khởi chạy ứng dụng tiếp theo. Nhưng, nếu tôi, ví dụ, xóa trường duy nhất, hoặc một số thực thể khác (không phải hai được đề cập ở đây), hoặc tạo lại một trong những thực thể đó (xóa nó và viết một lần nữa trong công cụ mô hình được quản lý Xcode) nó có thể biến mất.

Không thể tìm thấy mối quan hệ nào với Tùy chọn trường hoặc hạn chế duy nhất trong công cụ đối tượng được quản lý. Chỉ có một điều tôi có thể nắm bắt - thực thể StoreObject này phải có thực thể con và được khởi tạo trực tiếp trong ngữ cảnh trước khi lưu.

Khi tôi tạo ra thực thể riêng biệt cho các cửa hàng không phải duy nhất không có các thuộc tính và là con của StoreObject thực thể - vấn đề chỉ biến mất

Cập nhật

Trong ý kiến ​​đã được yêu cầu cho mã ví dụ. Ngay cả những tình huống đơn giản nhất có thể gây ra lỗi này

//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 

Cập nhật 2

Đây là những gì tôi nhận được với lập luận 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'} 
+0

Thừa kế thực thể nên "chỉ hoạt động". Không có yêu cầu đặc biệt-- như với bất kỳ trường hợp nào khác, dữ liệu của bạn cần phải vượt qua bất kỳ quy tắc xác thực nào mà bạn có, nhưng đó là nó. Từ những gì bạn đã mô tả không có lý do rõ ràng tại sao nó sẽ thất bại, vì vậy nó sẽ giúp đỡ nếu bạn có thể bao gồm một số mã minh họa những gì đang thực sự xảy ra. –

+0

Các đối tượng trừu tượng không thể được khởi tạo trực tiếp. – quellish

+0

@quellish Giống như tôi đã nói - StoreObject không phải là thực thể trừu tượng –

Trả lời

2

Tôi nghĩ có hai vấn đề chồng chéo: vấn đề chính là ràng buộc duy nhất trên uuid. Tôi đã thử tạo một thiết lập tương tự cho riêng bạn và tình huống duy nhất mà tôi có thể tạo lại lỗi là nếu uuid có ràng buộc duy nhất.

Tôi lưu ý từ câu hỏi của bạn rằng bạn không tin ràng buộc duy nhất có liên quan, nhưng tôi nghĩ điều này là do vấn đề thứ hai: ban đầu tôi bị lúng túng vì nỗ lực của tôi để áp dụng ràng buộc duy nhất sẽ không hoạt động. Trong khi SQLDebug của bạn hiển thị thuộc tính UNIQUE cho uuid khi cơ sở dữ liệu được tạo:

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) 

thì không. Sau khi làm sạch, và một chút thử nghiệm, cuối cùng tôi đã có sự ràng buộc duy nhất để làm việc (theo nghĩa trên).Ngay khi tôi làm vậy, tôi bắt đầu gặp phải lỗi tương tự như bạn:

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' 

Sau đó, tôi đã cố xóa bỏ ràng buộc.

enter image description here

Và sự cố vẫn tiếp tục. Ngay cả khi tôi làm sạch bản dựng, hãy xóa ứng dụng khỏi trình mô phỏng và chạy lại: cùng một vấn đề đã xảy ra. Bằng cách nào đó, mặc dù trình soạn thảo mô hình dữ liệu cho thấy không có ràng buộc nào đối với uuid, một ứng dụng đang được áp dụng. Tôi nhìn XML giấu đi bên trong xcdatamodeld, và có nó là:

<entity name="UniqueStoreObject" representedClassName="UniqueStoreObject" parentEntity="StoreObject" syncable="YES"> 
    <attribute name="uuid" attributeType="String" syncable="YES"/> 
    <uniquenessConstraints> 
     <uniquenessConstraint> 
      <constraint value="uuid"/> 
     </uniquenessConstraint> 
    </uniquenessConstraints> 
</entity> 

Rõ ràng Xcode chỉ là không cập nhật mô hình để phản ánh thêm/xóa ràng buộc duy nhất. Tuy nhiên, nếu bạn thực hiện thay đổi khác đối với mô hình (thêm và xóa thuộc tính), định nghĩa UNIQUE cho uuid được áp dụng khi các bảng được tạo và lỗi biến mất.

Điều này phù hợp với các quan sát của riêng bạn:

Nhưng, nếu tôi, ví dụ, xóa lĩnh vực uniquing, hoặc một số Entity khác (không phải là hai đề cập ở đây), hoặc tạo một trong những đơn vị (xóa nó và viết lại trong công cụ mô hình quản lý Xcode) nó có thể biến mất.

Những thay đổi bạn thực hiện cho các thực thể hoặc thuộc tính khác trong mô hình gây ra bất kỳ thay đổi nào đối với các ràng buộc duy nhất có hiệu lực.

Khi bạn khắc phục sự cố này với Xcode, vấn đề chính trở nên rõ ràng hơn: Những hạn chế về tính duy nhất dường như không hoạt động với các phần phụ.

Tất cả đều là giải thích thay vì giải pháp. Tôi đoán một số mã cụ thể cho lớp con UniqueStoreObject của bạn, thay vì sử dụng các ràng buộc duy nhất của CoreData. Tôi ước tôi có một giải pháp tốt hơn, nhưng tôi hy vọng bạn có thể ngủ ngon hơn một chút ...

+0

Tôi đoán, giờ tôi có thể ngủ ngon hơn. Câu trả lời của bạn là những gì tôi đang tìm kiếm. Giải pháp mà tôi tìm thấy - tạo ra subentity NonuniqueStoreObject mà không có thuộc tính bổ sung nào và khởi tạo nó thay vì StoreObject. Trong trường hợp này mọi thứ hoạt động tốt –

Các vấn đề liên quan