EF級聯刪除


引言

 

 

在主表中指定Key,子表中指定Required后,並不會在數據庫中生成級聯刪除的外鍵。那怎么才能使EF在數據中生成級聯刪除的外鍵?

SQLServer數據庫中級聯刪除功能配置界面:

image

上圖中顯示只用[required]特性后生成的外鍵沒有級聯刪除動作。

 

看似正確的解決方案。(治標的處理方式)

版本:EF6.0.1 RC

一對多場景,在子對象映射中開啟級聯刪除情況下,刪除父對象將自動刪除其下所有子對象,需要注意一些事項:

  需要保證DbContext中已經加載了該父對象的所有子對象。

 X  如果DbContext內未加載子對象將不級聯刪除子對象,

 X 如DbContext只加載部分子對象也只級聯刪除這些子對象。

因此在查詢父對象只應該使用Include("子對象屬性名")查詢(請看示例代碼3)或者在DbContext另外把其下所有子對象查詢出來(請看示例代碼4),再進行對父對象的刪除方可級聯刪除子對象。

但注意以上所述情況只適用於關聯子項比較少的情況,數據量少的演示測試Demo可以,工作中應該杜絕該類解決方案的出現。

 

真正的解決方案(治本的處理方式)

 

以下摘自是EntityFrameWork 官網原文

----------------------------------------------------------------

You can configure cascade delete on a relationship by using the WillCascadeOnDelete method. If a foreign key on the dependent entity is not nullable, then Code First sets cascade delete on the relationship. If a foreign key on the dependent entity is nullable, Code First does not set cascade delete on the relationship, and when the principal is deleted the foreign key will be set to null.

You can remove these cascade delete conventions by using:

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>()
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>()

The following code configures the relationship to be required and then disables cascade delete.

modelBuilder.Entity<Course>()
    .HasRequired(t => t.Department)
    .WithMany(t => t.Courses)
    .HasForeignKey(d => d.DepartmentID)
    .WillCascadeOnDelete(false);

 

EF到底怎么搞定級聯刪除

 

Setting Cascade on a relation in EF designer instructs EF to execute DELETE statement for each loaded realated entity. It doesn't say anything about ON CASCADE DELETE in the database.

Setting Cascade deletion when using EF needs two steps:

  • Set Cascade on relation in EF designer. This instruct context that all loaded related entitiesmust be deleted prior to deletion of the parent entity. If this doesn't happen EF will throw exception because internal state will detect that loaded childs are not related to any existing parent entity even the relation is required. I'm not sure if this happens before execution of delete statement of the parent entity or after but there is no difference. EF doesn't reload related entities after executing modifications so it simply doesn't know about cascade deletes triggered in the database.
  • Set ON CASCADE DELETE on relation in database. This will instruct SQL to delete all related records which were not loaded to context in the time of deleting the parent.

The implementation of cascade deletes in EF is strange and quite inefficient but this is how it behaves and if you want to use it, you must modify your application to behaves correctly in this scenario.

 

 

總結

  1. 問題解決的時候我們應該從事由表及里,不能只停留在問題表面,而應該找出問題真實的原因。
  2. 在使用現有框架時,我們有必要把其基礎原理搞清楚,也有必要把其使用場景搞清楚。(就像物理中許多定理中都有一個假設條件,而這個假設條件是這個定理成立的充分條件)

 

參考

EF里一對一、一對多、多對多關系的配置和級聯刪除

Entity framework 級聯刪除注意事項

EF里的默認映射以及如何使用Data Annotations和Fluent API配置數據庫的映射

Enabling Cascade Delete

Entity Framework 4.3 delete cascade with code first (Poco)

Cascading Deletes in LINQ to SQL

Cascading deletes with Entity Framework - Related entities deleted by EF


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM