[英]Navigation property incompletely loaded after eager load
我使用類似於以下代碼的代碼來選擇大量對象,以供只讀:
using (DBContext db = new MyContextClass())
{
... data creation ...
db.SaveChanges();
}
using (DBContext db = new MyContextClass())
{
db.Configuration.LazyLoadingEnabled = false;
db.Configuration.ProxyCreationEnabled = false;
db.Configuration.AutoDetectChangesEnabled = false;
DbQuery data = db.Set(someType)
foreach (string propertyName op in somePropertieNames)
data = data.Include(propertyName);
foreach (object item in data.AsNoTracking())
ScanNavigatorsOf(item);
}
在ScanNavigatorsOf()
,我讀取了所有導航屬性,並注意到由foreach
循環產生的第一個對象具有不完整的集合和引用。 程序ScanNavigatorsOf(...)
我的ScanNavigatorsOf(...)
方法時,導航屬性的填充似乎尚未完成。 所有其他對象都具有完整的導航屬性。 我正在對此進行單元測試,因此我可以確保對象正確存儲在數據庫中。
如何等待加載的對象的導航集合和引用完全填充?
就像在ObjectContext.ObjectMaterialized Event中解釋的那樣,集合似乎沒有與主要對象同時實現,但是我怎么知道過程何時完成?
首先使用ToList()
加載所有數據,然后掃描導航屬性:
var queryableData = db.Set(someType).AsNoTracking();
var data = somePropertieNames.Aggregate(queryableData , (current, property) => current.Include(property)).ToList();
foreach (object item in data)
ScanNavigatorsOf(item);
我很確定您遇到關閉DetectChanges
。 這是EF在表面之下進行的多次調用,以確保已正確建立被跟蹤實體之間的所有關聯並與原始外鍵值匹配(這稱為“ 關系修正” )。 您可能有理由將其關閉,但正如Lerman&Miller在他們的書DbContext中所說 :
確定何時需要調用DetectChanges並不像看起來那么瑣碎。 實體框架團隊強烈建議您僅在遇到性能問題時才轉換為手動調用DetectChanges。 還建議僅對性能不佳的代碼部分選擇不使用自動DetectChanges,並在相關部分完成執行后重新啟用它。
最重要的是,您無需跟蹤即可獲取對象。 現在,在關聯方面,EF幾乎完全癱瘓了。
您應該讓DetectChanges
進行工作,或者在循環中調用它。 並啟用跟蹤功能,否則更改跟蹤程序將無法修復關聯。
foreach (object item in data)
{
db.ChangeTracker.DetectChanges();
ScanNavigatorsOf(item);
}
或者在循環運行之前打開AutoDetectChangesEnabled
,在ScanNavigatorsOf
,將運行觸發DetectChanges
眾多方法之一。
但是AsNoTracking
還有另一個AsNoTracking
。 關閉變更跟蹤的作用是,上下文不能用作身份映射 ,這意味着:它不能確保數據庫中的每個記錄都會准確地實現一次。
如果您的Includes
有一個1-n-1
關聯,請說Order-OrderLine-Product
,而不跟蹤每個OrderLine
,即使已經為先前的訂單行創建了“相同”產品,也將創建一個新的Product
實例。 只要您以只讀方式使用數據,這就不是什么大問題,但是一旦將它們附加到上下文(例如,用於復制),就會遇到重復的關鍵異常。
簡而言之:當關聯很重要時,讓變更跟蹤器執行其工作,並確保DetectChanges
調用DetectChanges
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.