[英]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.