У меня есть простая модель данных с двумя объектами: Person и Company. Человек может быть назначен многим компаниям, и компания может быть назначена многим лицам. Я заполнил базу данных одной компанией и двумя лицами и назначил всех лиц компании. В процессе заполнения базы данных, Core Data генерировать журналы представлены ниже:Правильный способ удаления объекта из отношения в базовых данных
CoreData: sql: INSERT INTO ZCOMPANY(Z_PK, Z_ENT, Z_OPT, ZNAME) VALUES(?, ?, ?, ?)
CoreData: sql: INSERT OR REPLACE INTO Z_1PERSONS(Z_1COMPANIES, Z_2PERSONS) VALUES (1, 2)
CoreData: sql: INSERT OR REPLACE INTO Z_1PERSONS(Z_1COMPANIES, Z_2PERSONS) VALUES (1, 1)
CoreData: sql: INSERT INTO ZPERSON(Z_PK, Z_ENT, Z_OPT, ZNAME) VALUES(?, ?, ?, ?)
CoreData: sql: INSERT INTO ZPERSON(Z_PK, Z_ENT, Z_OPT, ZNAME) VALUES(?, ?, ?, ?)
Далее я закрыть приложение, запустить его снова и удалить компанию. Основные данные выполняют следующие операции затем:
CoreData: sql: SELECT 0, t0.Z_PK FROM Z_1PERSONS t1 JOIN ZPERSON t0 ON t0.Z_PK = t1.Z_2PERSONS WHERE t1.Z_1COMPANIES = ?
CoreData: annotation: sql connection fetch time: 0.0009s
CoreData: annotation: total fetch execution time: 0.0018s for 2 rows.
CoreData: annotation: to-many relationship fault "persons" for objectID 0x8d281e0 <x-coredata://0AFFC353-8C34-43AD-8D30-4483FB44BEA4/Company/p1> fulfilled from database.
Got 2 rows
CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZNAME FROM ZPERSON t0 WHERE t0.Z_PK = ?
CoreData: annotation: sql connection fetch time: 0.0008s
CoreData: annotation: total fetch execution time: 0.0016s for 1 rows.
CoreData: annotation: fault fulfilled from database for : 0x8e19940 <x-coredata://0AFFC353-8C34-43AD-8D30-4483FB44BEA4/Person/p1>
CoreData: sql: SELECT 0, t0.Z_PK FROM Z_1PERSONS t1 JOIN ZCOMPANY t0 ON t0.Z_PK = t1.Z_1COMPANIES WHERE t1.Z_2PERSONS = ?
CoreData: annotation: sql connection fetch time: 0.0009s
CoreData: annotation: total fetch execution time: 0.0022s for 1 rows.
CoreData: annotation: to-many relationship fault "companies" for objectID 0x8e19940 <x-coredata://0AFFC353-8C34-43AD-8D30-4483FB44BEA4/Person/p1> fulfilled from database.
Got 1 rows
CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZNAME FROM ZPERSON t0 WHERE t0.Z_PK = ?
CoreData: annotation: sql connection fetch time: 0.0006s
CoreData: annotation: total fetch execution time: 0.0014s for 1 rows.
CoreData: annotation: fault fulfilled from database for : 0x8e18f90 <x-coredata://0AFFC353-8C34-43AD-8D30-4483FB44BEA4/Person/p2>
CoreData: sql: SELECT 0, t0.Z_PK FROM Z_1PERSONS t1 JOIN ZCOMPANY t0 ON t0.Z_PK = t1.Z_1COMPANIES WHERE t1.Z_2PERSONS = ?
CoreData: annotation: sql connection fetch time: 0.0006s
CoreData: annotation: total fetch execution time: 0.0015s for 1 rows.
CoreData: annotation: to-many relationship fault "companies" for objectID 0x8e18f90 <x-coredata://0AFFC353-8C34-43AD-8D30-4483FB44BEA4/Person/p2> fulfilled from database.
Got 1 rows
CoreData: sql: BEGIN EXCLUSIVE
CoreData: sql: DELETE FROM ZCOMPANY WHERE Z_PK = ? AND Z_OPT = ?
CoreData: sql: DELETE FROM Z_1PERSONS WHERE Z_1COMPANIES = 1
CoreData: sql: UPDATE ZPERSON SET Z_OPT = ? WHERE Z_PK = ? AND Z_OPT = ?
CoreData: sql: UPDATE ZPERSON SET Z_OPT = ? WHERE Z_PK = ? AND Z_OPT = ?
CoreData: sql: COMMIT
Как мы видим выборки основных данных из базы данных всех лиц, назначенных удаляемой компании. Затем он получает коллекцию компаний для каждого человека. В конце концов, ожидаемые операции удаления выполняются на базе:
DELETE FROM ZCOMPANY WHERE Z_PK = ? AND Z_OPT = ?
DELETE FROM Z_1PERSONS WHERE Z_1COMPANIES = 1
Когда я удаляю компании, managedObjectContext ясно (нет объектов, зарегистрированных в нем), так что нет никаких оснований для очистки аннулированию отношения в памяти, потому что в памяти нет объектов. Единственное, что нужно сделать, это операции удаления на уровне базы данных, перечисленные выше.
Ситуация является проблемой, поскольку, когда у меня есть 1000 человек, назначенных для компании, операция удаления компании занимает слишком много времени (подсчитывается в секундах).
Что такое правильный способ удаления компании, которая выполняет только необходимую работу и обеспечивает согласованность данных?
Здесь вы можете загрузить проект Xcode, подготовленный для настоящей проблемы: Xcode project
Основные данные абсолютно безопасны для потоков. Всегда был. Люди часто путают «потокобезопасность» с «многопоточным доступом». Контекст не может быть доступен для нескольких потоков, но Core Data может и используется в многопоточной среде просто отлично.Такие вещи, как MagicalRecord, не улучшают безопасность потоков Core Data, они путаются с концепциями и затрудняют понимание базовой библиотеки. –
Тогда Apple тоже смущается: «Самостоявшиеся объекты не являются потокобезопасными». > https://developer.apple.com/library/ios/documentation/cocoa/conceptual/coredata/Articles/cdConcurrency.html ... –
Управляемые объекты не являются потокобезопасными. ** Основные данные ** являются потокобезопасными. Две разные вещи. Управляемые объекты ограничены потоком. –