2012-03-14 33 views
13

Tôi hơi mờ về cách xóa quy tắc cho các mối quan hệ trong Dữ liệu lõi, ít nhất là ngoài các trường hợp đơn giản được mô tả trong tài liệu.Quy tắc xóa dữ liệu lõi - mối quan hệ nhiều, xóa khi trống

Hầu hết các trường hợp đó và hầu hết các câu trả lời tôi đã thấy cho câu hỏi ở đây, sử dụng mô hình nơi đối tượng ở bên trái mối quan hệ một-nhiều "sở hữu" các đối tượng ở bên phải: ví dụ: a PersonPhoneNumber giây và nếu bạn xóa người bạn xóa tất cả các số được liên kết của họ. Trong đó loại trường hợp, giải pháp là rõ ràng: Core Dữ liệu sẽ xử lý tất cả mọi thứ cho bạn nếu bạn thiết lập các mối quan hệ như vậy:

Person  --(cascade)-->> PhoneNumber 
PhoneNumber --(nullify)--> Person 

Những gì tôi quan tâm là điều ngược lại: từ A đến-nhiều mối quan hệ nơi "quyền sở hữu" bị đảo ngược. Ví dụ, tôi có thể mở rộng mã mẫu CoreDataBooks để thêm một thực thể Author để thu thập tất cả thông tin về một tác giả duy nhất ở một nơi. A Book có một tác giả, nhưng tác giả có nhiều sách ... nhưng chúng tôi không quan tâm đến tác giả mà chúng tôi không liệt kê sách. Do đó, việc xóa một mối quan hệ Author có mối quan hệ books không được để trống và không được phép Book tham chiếu Author cụ thể mới nhất nên xóa Author.

tôi có thể tưởng tượng một vài cách để làm điều này bằng tay ... những gì tôi không chắc chắn của là:

  • không Core Data có một cách để làm ít nhất một số này automagically, như với quy tắc xóa mối quan hệ?
  • có cách nào "hợp lý", cách ưa thích để xử lý loại tình huống này không?

Trả lời

13

Bạn có thể ghi đè prepareForDeletion trong lớp Book và kiểm tra xem tác giả có bất kỳ sách nào khác không. Nếu không, bạn có thể xóa tác giả.

- (void)prepareForDeletion { 
    Author *author = self.author; 
    if (author.books.count == 1) { // only the book itself 
     [self.managedObjectContext deleteObject:author]; 
    } 
} 

Edit: Để ngăn chặn xóa của một tác giả với những cuốn sách bạn có thể ghi đè lên validateForDelete hoặc thậm chí tốt hơn: không gọi DeleteObject với một tác giả với những cuốn sách ở nơi đầu tiên

+2

Trừ khi có điều gì khác xảy ra, điều này dường như không thành công trong trường hợp, cả sách của tác giả đều bị xóa cùng một lúc. Tôi đang in ra giá trị của author.books.count trong tệp chuẩn tương ứng của tôi và nó là 2 cho cả hai cuốn sách. Sau đó, tác giả không bao giờ bị xóa. (tên lớp thay đổi để phù hợp với câu hỏi nhưng các mối quan hệ giống nhau.) –

1

Rickstr,

Kiểm tra dưới đây cho các mối quan hệ để có được hai tiêu chí của bạn thực hiện.

  1. Tác giả - (Deny) - >> Sách

xóa một tác giả có mối quan hệ sách không bị để trống không nên được phép

DENY : Nếu có ít nhất một đối tượng tại điểm đến mối quan hệ, thì đối tượng nguồn không thể bị xóa.

  1. Sách - (Cascade) -> Tác giả

xóa Sách cuối cùng tham khảo một Tác giả đặc biệt nên xóa mà Author

Bạn không thể xóa Tác giả, như quy tắc đầu tiên của chúng tôi đang nói, nếu có bất kỳ Sách nào không trống thì không được xóa. Nếu họ không có mặt thì Tác giả sẽ bị xóa.

Tôi nghĩ về mặt lý thuyết nó sẽ hoạt động. Hãy cho tôi biết, nếu điều này có hiệu quả hay không.

+0

'Tác giả - (Deny) - >> Sách' là tốt, nhưng 'Sách - (Cascade) -> Tác giả' khiến tác giả bị xóa ngay sau khi cuốn sách của tác giả đó bị xóa. (Hoặc là hoặc tôi đang làm điều gì đó sai.) – rickster

+0

Nhưng cùng một tác giả được ràng buộc với quyền liên quan DENY, Vì vậy về mặt lý thuyết nó sẽ không bị xóa, như ông có một cuốn sách khác. –

1

Tương tự như giải pháp của Tim, bạn có thể ghi đè phương thức willSave trong lớp con của tác giả NSManagedObject. Lưu ý rằng nếu bạn sử dụng giải pháp của Tim, tôi khuyên bạn nên lọc sách được đặt cho sách chưa bị xóa; theo cách này, nếu bạn xóa tất cả các sách của tác giả cùng một lúc, Tác giả sẽ vẫn bị xóa.

- (void)willSave { 
    if (!self.isDeleted) { 
     NSPredicate *notDeletedPredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary<NSString *,id> *bindings) { 
      return ![(NSManagedObject *)evaluatedObject isDeleted]; 
     }]; 
     NSSet *filteredBooks = [self.books filteredSetUsingPredicate:notDeletedPredicate]; 
     if (filteredBooks.count == 0) 
      [self.managedObjectContext deleteObject:self]; 
    } 
    [super willSave]; 
} 
Các vấn đề liên quan