Linq Entry(entity.Related).Query.Load() 没有写回 Collection 属性

Posted

技术标签:

【中文标题】Linq Entry(entity.Related).Query.Load() 没有写回 Collection 属性【英文标题】:Linq Entry( entity.Related ).Query.Load() not writing back to Collection property 【发布时间】:2016-12-20 09:06:49 【问题描述】:

假设我有三个 EF 实体类:

公共类人 ... 公共ICollection车辆得到;放; 公共类车辆 ... 公共人员所有者 获取;放; 公共汽车模型模型信息 获取;放; 公共类汽车模型 ... // 品牌、型号、颜色等属性

Person.Vehicles 属性是延迟加载的。

假设我已经加载了一个 Person 实例,并且我想加载它的 Vehicle 集合属性,以便它还包含相关的 ModelInfo 属性。

所以我有这个:

void LoadVehiclesAndRelated(MyDbContext dbContext, Person person)

    dbContext.Entry( person )
        .Collection( p => p.Vehicles )
        .Query()
        .Include( v => v.ModelInfo )
        .Load();

这样使用:

using( MyDbContext dbContext = ... ) 

    Person p = GetPerson( 123 );

    LoadVehiclesAndRelated( dbContext, p );


foreach(Vehicle v in p.Vehicles) 
    Console.WriteLine( v.ModelInfo );

但是,当我这样做时,我在运行时第一次计算 p.Vehicles 表达式时遇到异常,因为该属性实际上是空的(因此它想要加载它)但 DbContext 现在已被释放。

当调用.Load() 时(在LoadVehiclesAndRelated() 内部,我看到SQL 正在对服务器执行(在SQL Server Profiler 中),但集合属性仍然为空。

然后如何加载属性和 Included 子属性?

令人讨厌的是,MSDN 指南中没有提到这种情况的显式加载:https://msdn.microsoft.com/en-us/data/jj574232.aspx

【问题讨论】:

为了清楚起见,LoadVehiclesAndRelated 中的dbContext 变量与封闭的using( MyDbContext context = ... 相同? @IvanStoev 是的 - 我会澄清我的问题 【参考方案1】:

貌似调用.Query().Load()和直接调用DbCollectionEntry.Load不一样,重要的区别是前者没有设置IsLoaded属性,导致后面触发延迟加载。很可能是因为如链接中所述,前者旨在用于过滤(部分)收集负载场景。

简而言之,要解决此问题,只需在加载集合后将 IsLoaded 设置为 true:

var entry = dbContext.Entry(person);
var vehicleCollection = entry.Collection(p => p.Vehicles);
vehicleCollection.Query()
    .Include( v => v.ModelInfo )
    .Load();
vehicleCollection.IsLoaded = true;

附:为了正确起见,这种行为在在显式加载相关实体时应用过滤器部分的末尾有所提及:

使用 Query 方法时,通常最好关闭导航属性的延迟加载。这是因为否则整个集合可能会在执行过滤查询之前或之后通过延迟加载机制自动加载。

【讨论】:

以上是关于Linq Entry(entity.Related).Query.Load() 没有写回 Collection 属性的主要内容,如果未能解决你的问题,请参考以下文章

LINQ where 子句中的 async/await 不起作用

webpack的 entry

Entry.objects.filter() 或 Entry.objects.get() 如何工作?

如何更改 ttk.Entry 上的字体

webpack 多entry 配置

Map.Entry说明