2014-06-17 1 views
2

У меня есть простая модель данных с двумя объектами: 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

ответ

2

основных данных не является базой данных. Core Data - это иерархия объектов, которую может сохраняться в базе данных.

Это важное различие в таких случаях. Когда вы удаляете что-то, Core Data будет извлекать объекты с обеих сторон отношения, чтобы убедиться, что ссылочная целостность сохранена. С SQLite это кажется неэффективным (и это так). Когда в магазине что-то еще, эта двойная проверка требуется.

Итак, как это исправить? Один из них заключается в том, чтобы подтвердить, что удаление будет занимать некоторое время и развернуть фон, частную очередь, для обработки удалений. Не оптимально.

Другим вариантом является использование мягкой ссылки между этими двумя таблицами. Опять не идеальный.

Если вы можете подождать до iOS 8, вы можете выполнить пакетное обновление, чтобы отключить связь.

0

Общим обходным решением проблем с производительностью с CoreData является длительная обработка в фоновом потоке. К сожалению, это непростая задача, CoreData не является потокобезопасной.

Здесь можно использовать сторонние компоненты, такие как MagicalRecord, look at this document для получения дополнительной информации о том, как «Сохранить в фоновом потоке».

+1

Основные данные абсолютно безопасны для потоков. Всегда был. Люди часто путают «потокобезопасность» с «многопоточным доступом». Контекст не может быть доступен для нескольких потоков, но Core Data может и используется в многопоточной среде просто отлично.Такие вещи, как MagicalRecord, не улучшают безопасность потоков Core Data, они путаются с концепциями и затрудняют понимание базовой библиотеки. –

+0

Тогда Apple тоже смущается: «Самостоявшиеся объекты не являются потокобезопасными». > https://developer.apple.com/library/ios/documentation/cocoa/conceptual/coredata/Articles/cdConcurrency.html ... –

+0

Управляемые объекты не являются потокобезопасными. ** Основные данные ** являются потокобезопасными. Две разные вещи. Управляемые объекты ограничены потоком. –

 Смежные вопросы

  • Нет связанных вопросов^_^