2017年2月13日 星期一

[Entity Framework]原來是Cache!用AsNoTracking()揭穿他的真面目!

很好,太好了,我又見鬼啦!
但是我並不害怕,我盯著他看了好久好久,閉著眼都可以畫出他的樣子。
就讓我好好的描述描述他到底長個甚麼樣!

小弟我使用Entity Framework製作讀取資料庫中關聯式資料,實作中將DbContext.Configuration.LazyLoadingEnabled設定為true,便可以在一次執行中將所有關聯資料都同時撈出放在單一實體中。

但是,在一次讀取後,根據讀取的關聯資料進行修改並再次讀取時,恐怖的事情就發生啦!

剛剛更改的東西讀不到啊!

經過一番折騰發現原來Entity Framework有Cache機制,若要強制讀取新的資料可以使用AsNoTracking()。

馬上利用先前介紹威猛的LINQPad來做個小實驗。

首先介紹一下所查詢的Account以及Role兩張關聯資料表的關係:

接著是C#的查詢程式碼:
var dbContext = new HowardDBContext();
dbContext.Configuration.LazyLoadingEnabled = true;

//第一次查詢
var howardAccount = 
    dbContext.Account.Where(p=>p.AccountName == "Howard").First();
"第一次查詢帳號關聯出去的角色名稱:".Dump();
howardAccount.Role.RoleName.Dump();

//更新角色名稱admin->newAdmin
var cmd = 
    "update Role set RoleName = 'newAdmin' where RoleName = 'admin'";
dbContext.Database.ExecuteSqlCommand(cmd);

//第二次查詢
howardAccount = 
    dbContext.Account.Where(p=>p.AccountName == "Howard").First();
"第二次查詢帳號關聯出去的角色名稱:".Dump();
howardAccount.Role.RoleName.Dump();

//使用AsNoTracking
howardAccount = 
    dbContext.Account.AsNoTracking()
        .Where(p=>p.AccountName == "Howard").First();
"使用AsNoTracking查詢帳號關聯出去的角色名稱:".Dump();
howardAccount.Role.RoleName.Dump();

以及執行的結果:

從結果可以看到,第二次查詢前已經修改了資料庫中的資料,但查詢出來的結果仍為admin。
而使用AsNoTracking()則能查出關聯最新的資料(newAdmin)。

喔耶!捉鬼成功!阿彌陀佛!

p.s. LINQPad真的用起來有種莫名的爽感!

沒有留言:

張貼留言