有人可以向我解釋爲什麼我的EF(4.3)代碼首先下面的代碼導致「舊」密碼被檢索。EF 4.3使用本地緩存而不是從數據庫重新獲取
using (var context = new CableSenseInstanceConfiguratorContext())
{
var user = context.Installers.Where(u => u.UserName == "admin").FirstOrDefault();
Console.WriteLine(user.Password); // Outputs "oldpassword"
// Change the details on a different context;
using (var context2 = new CableSenseInstanceConfiguratorContext())
{
var installer = context2.Installers.Single(i => i.UserName == "admin");
installer.Password = "changed";
context2.SaveChanges();
}
var user2 = context.Installers.Where(u => u.UserName == "admin").FirstOrDefault();
Console.WriteLine(user2.Password); // Outputs "oldpassword"
}
密碼是「oldpassword」開始。所以我在另一個上下文(context2)中更改密碼,然後再次將其提取到user2中。我可以驗證兩者的輸出是「oldpassword」。從分析SQL,我可以看到密碼確實發生了變化,我還可以看到填充到數據庫的代碼,但它只是不使用這些值。
據我所知,英孚已經在本地上下文緩存和跟蹤實體的方法的概念,但是從我的理解,一個context.Installers.Where(..)
應該強制從數據庫中重新讀取,而context.Installers.Find()
應該看看當地的情況。看來,無論我如何查詢安裝程序,它都使用本地緩存。
EDIT
由於@Reinard的溶液。我被誤解的文檔 - 我從here閱讀:
注意DbSet和IDbSet始終對數據庫 創建查詢和總會涉及往返於即使 實體已經返回數據庫中存在的背景下, 。
所以我認爲,因爲它會去數據庫,它會重新獲取我的對象。究竟發生了什麼,它到了數據庫,取得了對象,發現我已經在跟蹤那個對象(因爲之前的負載),所以我最終得到了舊對象 - 這實際上是文檔說的!
使用context.Installers.Local.Clear()
沒什麼區別奇怪的是,我需要AsNoTracking().
你確定你正在比較相同的記錄嗎?在第一個上下文中,您正在使用.Where(...)。FirstOrDefault()和第二個上下文中使用.Single(...)。生成的SQL是否相同? – Maarten 2012-07-09 10:29:35
我不能重現描述的行爲,並同意whit @Maarten – tschmit007 2012-07-09 10:37:13
絕對100%肯定 - 唯一不同的Linq表達式與我用來更新DB中的記錄的第二個上下文,所以它並不重要這個Linq很不同。分析器驗證正確的記錄得到更新 – 2012-07-09 11:57:57