Entity Framework中的Identity map和Unit of Work模式(轉)

一,什麼是Identity map模式

Identity map是EF獲取和緩存數據的模式。
Identity map模式指的是任何數據都只會被加載一次,以map的形式緩存,以唯一的identity來再次獲取這些數據。
在EF中,就是在一個Context的生命週期中,所有查詢過的數據都會緩存到Context的local中緩存。當再次訪問這些數據的時候,就會以主鍵(identity)從緩存中獲取這些數據。

二,關於Identity map模式的驗證示例

看看下面這段代碼運行的結果:

複製代碼
using (var context = new SchoolContext())
{
       result1 = context.Students.ToList();
       result1[0].Age = -1;
       result2 = context.Students.ToList();

       var s1 = context.Students.First(s => s.Id == 1);
       var s2 = context.Students.First(s => s.Id == 1);
       var s3 = context.Students.First(s => s.Id == 3);
       var s4 = context.Students.First(s => s.Id == 3);

       Debug.Assert(ReferenceEquals(s1, s2));
       Debug.Assert(ReferenceEquals(s3, s4));
 }
複製代碼

運行之後,會發現s1和s2是同一個引用,s3和s4也是同一個引用。
原因就是在Identity map模式來說,對於唯一的主鍵,返回的必然是同一個對象。

再來看一個更加有趣的例子

複製代碼
public IEnumerable<Student> GetStudents()
{
       List<Student> result1;
       List<Student> result2;
       using (var context = new SchoolContext())
       {
           result1 = context.Students.ToList();
           result1[0].Age = -1;
           result2 = context.Students.ToList();
       }
       return result2;
}
複製代碼

實際的數據庫中的result1[0].Age是18,如果修改Age是-1, 再次執行context.Students.ToList(), 返回數據的Age並不是數據庫中的18,而是-1.

image

 

image

但是根據MiniProfiler的監控結果,EF的確訪問了2次數據庫

image

 

從這裏,得出的結論是:

Context在一次查詢結束後,得到的數據會保存到本地緩存,在提交之前對數據的修改都是在本地進行。
當再次Qeury的時候,Context中不存在的數據會放到Context中,Context已經存在的數據(即使被修改了),也不會被數據庫的數據覆蓋。

三. Unit of Work 模式

Unit of Work模式指的是:

所有對於context中查詢得到的實體對象的數據修改,都只會在調用SaveChanges方法後,纔會真正的保存到數據庫中。你可以在一個Context的生命週期中,修改多個實體對象的值,然後一次提交保存。
在EF中,由於Unit of Work模式,沒有辦法做選擇性的保存數據,只要是數據發生了改動,都會在SaveChnage方法中一併提交到數據庫中保存。

四,總結和注意問題

結合這兩種模式,可以看出
在一個Context的生命週期中,一個Entity只會有一個實例,任何對該實例的修改,即使這些改動沒有保存到數據庫中,修改都會影響到整個Context的生命週期。

注意問題:

1. 在使用EF的時候,理想的方式應該是 獲取數據-> 修改數據,保存數據->獲取數據……的過程。
不要在修改數據的過程中,再次請求數據,因爲這些數據很可能和數據庫中的數據不一致。

2. 在顯示層,最好使用ViewModel, 而不要直接使用EF中Model.
比如一篇博客文章中,我只想顯示前500個字給非註冊用戶看,如果使用Model, 不小心直接將文章內容的字段修改了,只保留了500個字,然後最後調用了SaveChange,用來保存文章的閱讀次數。
這樣就會導致文章內容被我不小心給丟失了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章