7

Tôi đã tìm kiếm trong SO nhưng tôi không tìm thấy bất kỳ đề xuất nào để tăng hiệu suất khi xóa đối tượng được quản lý trong dữ liệu lõi khi xử lý mối quan hệ.Cân nhắc hiệu suất khi xóa đối tượng được quản lý bằng cách sử dụng quy tắc Cascade trong dữ liệu lõi

Kịch bản khá đơn giản. enter image description here

Như bạn có thể thấy có ba thực thể khác nhau. Mỗi thực thể được liên kết trong tầng với tiếp theo. Ví dụ: FirstLevel có mối quan hệ được gọi là secondLevels đến SecondLevel. Quy tắc xóa từ FirstLevel đến SecondLevelCascade trong khi quy tắc xóa từ SecondLevel đến FirstLevelNullify. Các quy tắc tương tự được áp dụng giữa SecondLevelThirdLevel.

Khi tôi muốn xóa toàn bộ đồ thị, tôi thực hiện một phương pháp như sau:

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]; 
} 

Lợi dụng các Cascade cai trị đồ thị được lấy ra. Điều này làm việc nhanh cho vài đối tượng nhưng giảm hiệu suất cho nhiều đối tượng. Ngoài ra, tôi nghĩ (nhưng tôi không chắc chắn) rằng loại xóa này thực hiện rất nhiều chuyến đi vòng vào đĩa, Tôi có sai không? Vì vậy, câu hỏi của tôi là như sau: làm thế nào là nó có thể loại bỏ các đồ thị mà không tận dụng lợi thế của quy tắc Cascade và tăng hiệu suất, nhưng, cùng một lúc, duy trì tính nhất quán của đồ thị?

Cảm ơn bạn trước.

EDIT

tôi không thể xóa toàn bộ tập tin kể từ khi tôi có các đơn vị khác trong mô hình của tôi.

EDIT 2

Code tôi gửi được gói trong các phương pháp main của một lớp con NSOperation. Giải pháp này cho phép các giai đoạn xóa được excuted trong nền. Vì tôi đã tận dụng lợi thế của Quy tắc Cascade việc xóa được thực hiện theo cách bán tự động. Tôi chỉ xóa các đối tượng gốc, các mục FirstLevel, bằng vòng lặp for trong mã được đăng. Theo cách này, Core Data sẽ làm phần còn lại cho tôi. Những gì tôi tự hỏi là sau đây: là nó có thể bybass rằng hoạt động xóa bán tự động và làm điều đó bằng tay mà không làm mất tính nhất quán của đồ thị?

+0

Bạn có muốn xóa toàn bộ biểu đồ, ý tôi là, xóa tất cả các cửa hàng liên tục hay chỉ một số chi nhánh? –

+0

Toàn bộ biểu đồ. –

+1

Sau đó, điều này sẽ giúp bạn? Http: //stackoverflow.com/questions/3266084/how-to-remove-all-objects-from-core-data –

Trả lời

5

Bạn không thể làm nhiều về thời gian cần thiết để duyệt và loại bỏ các đối tượng trong cơ sở dữ liệu. Tuy nhiên, bạn có thể làm điều đó trong nền để giao diện người dùng không bị chặn.

Ví dụ, một cái gì đó giống như (mã giả ARC - và chỉ gõ - không biên soạn) ...

- (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]; 
    }]; 
} 

Lưu ý, rằng bạn có thể thêm một đối tượng RootLevel để mô hình dữ liệu của bạn, và cung cấp cho nó một mối quan hệ một-nhiều đối với các đối tượng cấp một. Sau đó, (miễn là bạn chỉ có một đối tượng gốc), tất cả những gì bạn phải làm là xóa một đối tượng gốc và nó sẽ xóa mọi thứ khác bên trong CoreData. Nếu bạn có nhiều đối tượng FirstLevel, đó sẽ là cách để đi.

Hoặc, bạn có thể kết nối ngữ cảnh "mới" của mình trực tiếp với cửa hàng liên tục, thực hiện thay đổi và có ngữ cảnh khác xem thông báo thay đổi.

BTW, nếu bạn đang sử dụng UIManagedDocument, bạn sẽ nhận được loại nền này miễn phí, vì đã có một bối cảnh cha mẹ chạy trên hàng đợi của chính nó, và tất cả thay đổi đối với ngữ cảnh chính được truyền cho phụ huynh công việc cơ sở dữ liệu.

EDIT

Bạn có thể làm nó bằng tay, nhưng bạn phải tắt các quy tắc thác. Tôi đã thấy rằng tôi muốn CoreData làm nhiều nhất có thể. Nó làm giảm biên độ của tôi cho lỗi.

Nếu bạn đã xóa trong chuỗi nền, thì bạn thấy vấn đề hiệu suất như thế nào? Bạn phải truy vấn trong quá trình xóa ... có nghĩa là bạn đang sử dụng MOC thực hiện tất cả công việc.

Bạn nên học một bài học từ UIManagedDocument. bạn nên có một MOC chạy trên một hàng đợi riêng. Nó làm tất cả công việc thực sự. Bạn có một MOC con chỉ chuyển công việc tới hàng đợi của nhân viên đó.

Nếu bạn đang thực sự truy vấn đối tượng không có trong biểu đồ bạn đang xóa, chúng có thể bị treo lên bởi các thuộc tính tuần tự hóa của điều phối viên lưu trữ liên tục. Nếu đúng như vậy, bạn nên xem xét một điều phối viên riêng biệt, hoặc chỉ có hai cửa hàng.

Bằng cách đó, bạn có thể xóa các đối tượng trong biểu đồ của mình miễn là bạn muốn, trong khi vẫn đáp ứng yêu cầu cho các đối tượng khác.

+0

+1 để được hỗ trợ. Tôi đã xóa trong một chủ đề trở lại. Bạn có thể giải thích tốt hơn ý của bạn với * bạn có thể kết nối ngữ cảnh "mới" của bạn trực tiếp với cửa hàng liên tục, thực hiện thay đổi và có ngữ cảnh khác để xem thông báo thay đổi * không? Cảm ơn bạn. –

+0

Có thể đăng toàn bộ mã xóa của bạn sau đó ... Đối với phần thứ hai, bạn có thể tạo nhiều MOC sử dụng cùng NSPersistentStoreCoordinator. Tuy nhiên, điều này sẽ tuần tự hóa truy cập vào cửa hàng ... Bạn cũng có thể tạo một NSPersistentStoreCoordinator riêng biệt, và sau đó bạn sẽ có quyền truy cập song song vào cửa hàng ... nhưng bạn có các vấn đề khác để giải quyết. Nói chung, giải pháp đơn giản nhất luôn là tốt nhất. –

+0

Cảm ơn bạn đã trả lời. Tạo nhiều MOC có thể là một giải pháp hợp lệ nhưng tôi cần phải hoàn thành việc xóa trong một lần truyền. Xem bản chỉnh sửa thứ hai của tôi. Cám ơn bạn một lần nữa. –

1

Tôi thường bật truy vấn SQL dữ liệu lõi với -com.apple.CoreData.SQLDebug 1 như được mô tả tại đây: http://useyourloaf.com/blog/2010/3/11/debugging-core-data-on-the-iphone.html Điều này giúp kiểm tra Dữ liệu cốt lõi thực hiện những gì tôi mong đợi để thực hiện sau hậu trường.

Bạn có chắc chắn rằng [lưu trữ moc: ...] mất nhiều thời gian và không thực hiện tìm nạp thực tế để tìm nạp các đối tượng cần xóa không? Nếu đúng như vậy, bạn có thể tìm nạp (và sau đó xóa) các đối tượng firstlevel theo lô.