Khung thực thể .Remove () so với .DeleteObject ()


141

Bạn có thể xóa một mục khỏi cơ sở dữ liệu bằng cách sử dụng hai phương pháp sau.

Đầu tiên là trên EntityCollectionvà thứ hai trênObjectContext .

Khi nào nên sử dụng mỗi?

Là một người thích hơn người khác?

Remove()trả về a boolDeleteObject()trả về void.

Câu trả lời:


275

Nói chung không đúng khi bạn có thể " xóa một mục khỏi cơ sở dữ liệu " bằng cả hai phương pháp. Nói chính xác là như vậy:

  • ObjectContext.DeleteObject(entity)đánh dấu các thực thể nhưDeleted trong bối cảnh. (Đó EntityStateDeletedsau đó.) Nếu bạn gọi SaveChangessau đó, EF sẽ gửi một câu lệnh SQL DELETEđến cơ sở dữ liệu. Nếu không có ràng buộc tham chiếu nào trong cơ sở dữ liệu bị vi phạm, thực thể sẽ bị xóa, nếu không sẽ có ngoại lệ.

  • EntityCollection.Remove(childEntity)đánh dấu mối quan hệ giữa cha mẹ và childEntitynhưDeleted . Nếu childEntitychính nó bị xóa khỏi cơ sở dữ liệu và chính xác những gì xảy ra khi bạn gọi SaveChangesphụ thuộc vào loại mối quan hệ giữa hai:

    • Nếu mối quan hệ là tùy chọn , tức là khóa ngoại tham chiếu từ con đến cha mẹ trong cơ sở dữ liệu cho phép NULLcác giá trị, thì ngoại lệ này sẽ được đặt thành null và nếu bạn gọi giá trị SaveChangesnày sẽ được ghi vào cơ sở dữ liệu (nghĩa là mối quan hệ giữa hai cái bị loại bỏ). Điều này xảy ra với một câu lệnh SQL . Không có tuyên bố xảy ra.NULLchildEntityUPDATEDELETE

    • Nếu mối quan hệ là bắt buộc (FK không cho phép NULLcác giá trị) và mối quan hệ không được xác định (có nghĩa là khóa ngoại không phải là một phần của khóa chính (tổng hợp) của trẻ), bạn phải thêm con vào cha mẹ khác hoặc bạn phải xóa con một cách rõ ràng ( DeleteObjectsau đó). Nếu bạn không thực hiện bất kỳ ràng buộc tham chiếu nào bị vi phạm và EF sẽ đưa ra một ngoại lệ khi bạn gọi SaveChanges- câu nói nổi tiếng " Mối quan hệ không thể thay đổi vì một hoặc nhiều thuộc tính khóa ngoài là ngoại lệ " giống.

    • Nếu mối quan hệ được xác định (nó nhất thiết phải yêu cầu sau đó vì bất kỳ một phần của khóa chính không thể NULL) EF sẽ đánh dấu childEntitynhư Deletedlà tốt. Nếu bạn gọi SaveChangesmột câu lệnh SQL DELETEsẽ được gửi đến cơ sở dữ liệu. Nếu không có ràng buộc tham chiếu nào khác trong cơ sở dữ liệu bị vi phạm, thực thể sẽ bị xóa, nếu không sẽ có ngoại lệ.

Tôi thực sự hơi bối rối về phần Ghi chú trên trang MSDN mà bạn đã liên kết vì nó nói: " Nếu mối quan hệ có ràng buộc toàn vẹn tham chiếu, việc gọi phương thức Remove trên một đối tượng phụ thuộc sẽ đánh dấu cả mối quan hệ và đối tượng phụ thuộc để xóa. ". Điều này có vẻ không chính xác hoặc thậm chí sai đối với tôi bởi vì cả ba trường hợp trên đều có " ràng buộc toàn vẹn tham chiếu " nhưng chỉ trong trường hợp cuối cùng, đứa trẻ thực tế đã bị xóa. (Trừ khi chúng có nghĩa là với " đối tượng phụ thuộc ", một đối tượng tham gia vào một mối quan hệ xác định sẽ là một thuật ngữ bất thường.)


2
Tính toàn vẹn tham chiếu wikipedia: Tính toàn vẹn tham chiếu là một thuộc tính của dữ liệu, khi được thỏa mãn, yêu cầu mọi giá trị của một thuộc tính (cột) của một quan hệ (bảng) tồn tại như một giá trị của thuộc tính khác trong một mối quan hệ (hoặc cùng) khác ), vì vậy khi mối quan hệ là Tùy chọn, chúng tôi sẽ phá vỡ quy tắc Liêm chính dữ liệu
Mohammadreza

3
@Mohammadreza: Nếu bạn diễn giải NULLlà "Không phải là giá trị" (thay vì "giá trị NULL" như tôi đã viết đôi khi hơi cẩu thả) thì "mối quan hệ tùy chọn" không mâu thuẫn với định nghĩa về tính toàn vẹn tham chiếu.
Slauma

1
Vậy phiên bản EF Core là ObjectContext.DeleteObjectgì?
Jonathan Allen

13

Nếu bạn thực sự muốn sử dụng Đã xóa, bạn phải biến các khóa ngoại của mình thành không thể, nhưng sau đó bạn sẽ kết thúc với các bản ghi mồ côi (đó là một trong những lý do chính bạn không nên làm điều đó ngay từ đầu). Vì vậy, chỉ cần sử dụngRemove()

ObjectContext.DeleteObject (thực thể) đánh dấu thực thể là Đã xóa trong ngữ cảnh. (Đó là EntityState bị xóa sau đó.) Nếu bạn gọi SaveChanges sau đó, EF sẽ gửi một câu lệnh XÓA SQL đến cơ sở dữ liệu. Nếu không có ràng buộc tham chiếu nào trong cơ sở dữ liệu bị vi phạm, thực thể sẽ bị xóa, nếu không sẽ có ngoại lệ.

EntityCollection.Remove (childEntity) đánh dấu mối quan hệ giữa cha mẹ và childEntity là Đã xóa. Nếu chính childEntity bị xóa khỏi cơ sở dữ liệu và chính xác điều gì sẽ xảy ra khi bạn gọi SaveChanges tùy thuộc vào loại mối quan hệ giữa hai:

Một điều đáng chú ý là cài đặt .State = EntityState.Deleted không kích hoạt tự động phát hiện thay đổi. ( lưu trữ )


4
Ok, đối với những người bỏ phiếu xuống, câu trả lời của tôi không liên quan gì đến Slauma - cả hai đều chỉ đến cùng một tài liệu . Mine giải thích các ví dụ thực tế trong khi phần lý thuyết của ông về nó.
Matas Vaitkevicius
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.