第12章定製EF在本章的小節里,定製實體對象和EF處理的一些功能.這些小節將涵蓋很多”幕後”的事情,能讓你的代碼更加統一解決一些事情,比如用一個業務規則中心統一地為實體執行驗證.本章開始的小節,將演示如何在你的應用程式中當調用SaveChanges() 時,執行你自己的代碼. 如果你想在你的應用程式...
第12章定製EF
在本章的小節里,定製實體對象和EF處理的一些功能.這些小節將涵蓋很多”幕後”的事情,能讓你的代碼更加統一解決一些事情,比如用一個業務規則中心統一地為實體執行驗證.
本章開始的小節,將演示如何在你的應用程式中當調用SaveChanges() 時,執行你自己的代碼. 如果你想在你的應用程式里單獨定製業務規則,本小節和有些小節非常有用.
在其它小節里,我們將演示如何跟蹤資料庫連接,如果自動報告集合的改變,如何實現級聯刪除,如何設定預設值,和如何與強類型的XML屬性一起使用.所有這些定製共同點就是擴展對象和EF處理過程使你的代碼更具彈性,統一性和可維護性.
12-1. 當SaveChanges( ) 被調用時執行你的代碼
問題
你想在data context 中SaveChanges()被調用時,執行你的代碼
解決方案
假設你有一個關於申請人的模型(如Figure 12-1所示). 申請人文檔做為模型的一部分,你想在Applicant被刪除時,文檔也一起刪除.你可能發現在你應用程式的每個刪除Applicant地方,都要刪除文檔,而你想用一個統一的方式來處理
Listing 12-1. Overriding SaveChanges() to Delete the Resume File When the Applicant Is Deleted
為確保文檔隨同applicant一起刪除, 我們在DbContext 里override SavingChanges() 方法, 我們需要先瀏覽DbContext里的實體,找出要被刪除的Applicant,然後調用真正的SaveChanges() 方法. 最後,為每個被刪除的Applicant刪除文件,代碼如Listing 12-1所示:
Listing 12-1. Overriding SaveChanges() to Delete the Resume File When the Applicant Is Deleted
class Program
{
static void Main(string[] args)
{
using (var context = new EFRecipesEntities())
{
var path1 = "AlexJones.txt";
File.AppendAllText(path1, "Alex Jones\nResume\n...");
var path2 = "JanisRogers.txt";
File.AppendAllText(path2, "Janis Rodgers\nResume\n...");
var app1 = new Applicant
{
Name = "Alex Jones",
ResumePath = path1
};
var app2 = new Applicant
{
Name = "Janis Rogers",
ResumePath = path2
};
context.Applicants.Add(app1);
context.Applicants.Add(app2);
context.SaveChanges();
//刪除 Alex Jones
context.Applicants.Remove(app1);
context.SaveChanges();
}
}
}
public partial class EFRecipesEntities
{
public override int SaveChanges()
{
Console.WriteLine("Saving Changes...");
var applicants = this.ChangeTracker.Entries().Where(e => e.State == System.Data.Entity.EntityState.Deleted)
.Select(e => e.Entity).OfType<Applicant>().ToList();
int changes= base.SaveChanges();
Console.WriteLine("\n{0} applicants deleted",applicants.Count().ToString());
foreach (var app in applicants)
{
File.Delete(app.ResumePath);
Console.WriteLine("\n{0}'s resume at {1} deleted",app.Name, app.ResumePath);
}
return changes;
}
}
上述Listing 12-1代碼輸出結果如下:
Saving Changes...
0 applicants deleted
Saving Changes...
1 applicants deleted
Alex Jones's resume at AlexJones.txt deleted
原理
Listing 12-1里的代碼,先插入兩個applicant同時創建他們各自的文檔.我們的目標是用統一的方式,當applicant被刪除時,他們的文檔也一同被刪除.我們通過override SaveChanges() 方法來實現.在我們的 SaveChanges() 方法中,首先收集所有將被刪除的Applicant實例, 接著我們調用真正的
SaveChanges() 方法,把它們從資料庫中刪除,最後在遍歷我們最開始收集的實例,在遍歷里刪除他們各自的文檔. 因為實體從資料庫刪除後,也會在context中刪除,我們不能再通過查詢找到context中被刪除的裸體,所以第一步里我們用了ToList()方法,先把要被刪除的實體保存到另一個對象中.
EF沒有實體的插入,更新,修改事件,但是很多想在這些事件里處理的事情,都可以像我們這裡的方式一樣,通過override SaveChanges() 方法實現.