7

我在SO內進行了搜索,但是在處理關係時,我沒有發現任何關於刪除核心數據中的被管理對象的性能的建議。關於在覈心數據中使用級聯規則刪除被管理對象的性能考慮

這個場景很簡單。 enter image description here

正如你所看到的,有三種不同的實體。每個實體都與下一個級聯鏈接。例如,FirstLevel具有secondLevelsSecondLevel的關係。從FirstLevelSecondLevel的刪除規則是級聯而從SecondLevelFirstLevel的刪除規則是否定。在SecondLevelThirdLevel之間應用相同的規則。

當我想要刪除整個圖中,我執行一種方法如下所示:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"FirstLevel" inManagedObjectContext:context]; 
[fetchRequest setEntity:entity]; 

NSError *error = nil; 
NSArray *items = [context executeFetchRequest:fetchRequest error:&error]; 
[fetchRequest release];  

// delete roots object and let Core Data to do the rest... 
for (NSManagedObject *managedObject in items) { 
    [context deleteObject:managedObject]; 
} 

服用級聯統治圖形被去除的優點。這對於少數物體可以快速工作,但會降低許多物體的性能。另外,我認爲(但我不太確定)這種類型的刪除對磁盤執行了很多往返操作,我錯了嗎?

因此,我的問題如下:如何在不利用Cascade規則和提升性能的情況下刪除圖表,但同時保持圖形一致性?

預先感謝您。

編輯

,因爲我在我的模型中的其他實體,我不能刪除整個文件。

編輯2

我發佈的代碼被包裝在NSOperation子類的main方法。該解決方案允許刪除階段在後臺執行。由於我利用了級聯規則刪除是以半自動方式執行的。我只通過發佈的代碼中的for循環刪除根對象,即FirstLevel項。以這種方式核心數據爲我做了其餘的。我想知道的是:是否有可能通過半自動刪除操作,並手動執行而不會失去圖形一致性?

+0

做tou想刪除整個圖,我的意思是,清除所有的持久性存儲,或只是一些分支? – 2012-04-17 08:57:50

+0

整個圖。 – 2012-04-17 09:03:14

+1

Thenmaybe這會幫助你嗎?http://stackoverflow.com/questions/3266084/how-to-remove-all-objects-from-core-data – 2012-04-17 09:15:53

回答

5

對於遍歷和刪除數據庫中的對象所花費的時間你無能爲力。但是,您可以在後臺執行此操作,以避免UI被阻止。

例如,像(代碼假設ARC - 和剛剛輸入 - 不編譯)...

- (void)deleteAllLevelsInMOC:(NSManagedObjectContext*)moc 
{ 
    // Create a context with a private queue, so access happens on a separate thread. 
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
    // Insert this context into the current context hierarchy 
    context.parentContext = context; 
    // Execute the block on the queue of the context 
    context.performBlock:^{ 
      NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"FirstLevel"]; 
      // This will not load any properties - just object id 
      fetchRequest.includesPropertyValues = NO; 
      // Iterate over all first-level objects, deleting each one 
      [[context executeFetchRequest:fetchRequest error:0] 
       enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
       [context deleteObject:obj]; 
      }]; 
      // Push the changes out of the context 
      [context save:0]; 
    }]; 
} 

注意,你可以一個根層次Rootlevel對象添加到您的數據模型,並給它一個與第一級對象的一對多關係。然後,(只要你只有一個根對象),你所要做的就是刪除這個根對象,它將刪除CoreData中的其他所有內容。如果你有很多FirstLevel對象,那就是要走的路。

或者,您可以將您的「新」上下文直接連接到持久性存儲,進行更改,並讓其他上下文監視更改通知。

順便說一句,如果你正在使用UIManagedDocument,你得到這種backgrounding免費的,因爲已經有它自己的隊列運行父上下文,並在右鍵所有的改變都將傳遞給實際做父數據庫工作。

編輯

你可以做手工,但你必須關閉級聯規則。我發現我希望CoreData儘可能爲我做很多事情。它減少了我的誤差。

如果您已經在後臺線程中刪除,那麼您如何看到性能問題?您在刪除期間必須查詢......這意味着您正在使用MOC來完成所有工作。

你應該從UIManagedDocument上一堂課。你應該有一個在私人隊列上運行的MOC。它完成了所有的實際工作。你有一個孩子MOC只是將工作傳遞給該工作者隊列。

如果您實際正在查詢不在您要刪除的圖形中的對象,它們可能會被持久存儲協調器的序列化屬性掛起。如果是這樣的話,你應該考慮一個單獨的協調員,或者只有兩個商店。

通過這種方式,您可以根據需要刪除圖形中的對象,同時仍能響應其他對象的請求。

+0

+1獲得支持。我已經在後臺線程中刪除了。你能否更好地解釋你的意思是什麼?你可以直接將你的「新」上下文連接到持久存儲,進行更改,並讓其他上下文關注更改通知*?謝謝。 – 2012-04-19 17:15:30

+0

也許會發布完整的刪除代碼,然後......至於第二部分,您可以創建多個使用相同NSPersistentStoreCoordinator的MOC。但是,這將序列化對商店的訪問...您也可以創建單獨的NSPersistentStoreCoordinator,然後您將可以並行訪問商店...但您還有其他問題需要處理。一般來說,最簡單的解決方案總是最好的。 – 2012-04-19 17:30:11

+0

謝謝你的回覆。創建多個MOC可能是一個有效的解決方案,但我需要一次完成刪除操作。看到我的第二個編輯。再次感謝你。 – 2012-04-19 18:25:04

1

我通常打開核心數據SQL跟蹤-com.apple.CoreData.SQLDebug 1如下所述:http://useyourloaf.com/blog/2010/3/11/debugging-core-data-on-the-iphone.html 這有助於檢查覈心數據做我希望它在幕後做。

您是否確定[moc save:...]需要那麼長時間,而不是實際的fetchrequest來獲取要刪除的對象?如果是這種情況,您可以批量獲取(然後刪除)這些firstlevel對象。

相關問題