2

我對實體框架中DbContext的用法有點困惑。這是我很困惑的場景。實體框架和DbContext - 對象跟蹤

  • 我使用dbcontext中的linq查詢來獲取數據。喜歡的東西:

    List<Transactions> transactions = DefaultContext.Transactions.ToList(); 
    
  • 然後我直接在數據庫在查詢返回的交易的一個更新的列。

  • 然後我再打電話:

    List<Transactions> transactions = DefaultContext.Transactions.ToList(); 
    

當列表返回這個時候,它並不能反映更新/運行更新語句時,除非我遍歷所有我所做的更改我的交易和重新加載他們:

foreach (DbEntityEntry<Transactions> item in DefaultContext.ChangeTracker.Entries<Transactions>()) 
{ 
    DefaultContext.Entry<Transactions>(item.Entity).Reload(); 
} 

這是正常的行爲?我假設在我最初的查詢中,它們被附加到對象上下文中。然後,當我第二次查詢時,它不會訪問數據庫,只是從對象上下文中提取實體,除非我清除/分離或單獨重新加載所有實體。

回答

8

這是正常的,並在DbContext API固定行爲的情況下,因爲從一些非常奇怪的原因既不DbSetDbQuery公開MergeOption屬性。在ObjectContext API的情況下,您可以在ObjectSetObjectQuery上設置暴露MergeOption的行爲。所以,如果你想從更新數據庫中的值(和丟失所做的更改),你可以這樣做:

ObjectContext objectContext = ((IObjectContextAdapter)dbContext).ObjectContext; 
ObjectSet<Transactions> set = objectContext.CreateObjectSet<Transactions>(); 
set.MergeOption = MergeOption.OverwriteChanges; 
List<Transactions> transactions = set.ToList(); 

如果你只是想刷新交易,但你不想失去你的改變,你可以使用MergeOption.PreserveChanges代替。

+0

我需要過濾一些返回的數據。我正在使用一個.Where(...之前,但是現在我使用的是ObjectContext,它不知道我的實體類。現在如何過濾查詢中的數據?我不想返回整個結果 – mservidio

+0

你的意思是「它不知道我的實體類」,你可以像寫DbContext一樣用ObjectContext編寫相同的linq查詢。 –

+0

沒關係,我完全錯過了它的設置... – mservidio

2

這取決於DefaultContext.Transactions查詢的MergeOption。默認值爲AppendOnly,won't overwrite objects already in your context.您可以將其更改爲OverwriteChanges以獲得您期望的行爲。

+0

感謝您指出了這一點。因爲我使用DbContext,所以我的查詢不是ObjectQuery類型。所以我不能像var query = Defaultcontext.Transactions; ((ObjectQuery)查詢).MergeOption = MergeOption.OverwriteChanges;我需要使用linq樣式查詢嗎? – mservidio

0

與上面相關的是,當我遇到同樣的錯誤時,這是​​我登陸的地方。但我想在我的情況下設置合併選項沒有跟蹤。當我有一個Excel導出方法試圖關閉IQueryable的對象跟蹤時,我遇到了這個問題。通過移動大量我不會改變的數據,我不需要任何更改跟蹤。

一行代碼類似於下面將在嘗試投一些IQueryables類的ObjectQuery失敗(但對別人成功。)

var y = ((ObjectQuery)query).MergeOption = MergeOption.NoTracking; 

相反,我換成這與AsNoTracking

的使用
query = query.AsNoTracking(); 

有關回到原來的問題,這可能會像下面,擴展DBQuery的方法在System.Data中添加。實體

List<Transactions> transactions = DefaultContext.Transactions.AsNoTracking().ToList(); 

半相關文章: https://msdn.microsoft.com/en-us/library/hh949853(v=vs.113).aspx