Linq Entry( entity.Related ).Query.Load() 没有写回 Collection 属性
Linq Entry( entity.Related ).Query.Load() not writing back to Collection property
假设我有三个 EF 实体 类:
public class Person {
...
public ICollection Vehicles { get; set; }
}
public class Vehicle {
...
public Person Owner { get; set; }
public CarModel ModelInfo { get; set; }
}
public class CarModel {
...
// properties for make, model, color, etc
}
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 中)但是集合 属性 保持为空。
然后如何加载 属性 和 Include
d 子属性?
令人讨厌的是,MSDN 指南中没有提到显式加载的这种情况:https://msdn.microsoft.com/en-us/data/jj574232.aspx
貌似调用.Query().Load()
和直接调用DbCollectionEntry.Load
不一样,重要的区别是前者没有设置IsLoaded
属性,后者然后导致稍后触发延迟加载。很可能是因为如 link 中所述,前者旨在用于过滤(部分)收集负载场景。
很快,要解决此问题,只需在加载集合后将 IsLoaded
设置为 true:
var entry = dbContext.Entry(person);
var vehicleCollection = entry.Collection(p => p.Vehicles);
vehicleCollection.Query()
.Include( v => v.ModelInfo )
.Load();
vehicleCollection.IsLoaded = true;
P.S。为了正确起见,这种行为在 显式加载相关实体时应用过滤器 部分的末尾有所提及:
When using the Query method it is usually best to turn off lazy loading for the navigation property. This is because otherwise the entire collection may get loaded automatically by the lazy loading mechanism either before or after the filtered query has been executed.
假设我有三个 EF 实体 类:
public class Person { ... public ICollection Vehicles { get; set; } } public class Vehicle { ... public Person Owner { get; set; } public CarModel ModelInfo { get; set; } } public class CarModel { ... // properties for make, model, color, etc }
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 中)但是集合 属性 保持为空。
然后如何加载 属性 和 Include
d 子属性?
令人讨厌的是,MSDN 指南中没有提到显式加载的这种情况:https://msdn.microsoft.com/en-us/data/jj574232.aspx
貌似调用.Query().Load()
和直接调用DbCollectionEntry.Load
不一样,重要的区别是前者没有设置IsLoaded
属性,后者然后导致稍后触发延迟加载。很可能是因为如 link 中所述,前者旨在用于过滤(部分)收集负载场景。
很快,要解决此问题,只需在加载集合后将 IsLoaded
设置为 true:
var entry = dbContext.Entry(person);
var vehicleCollection = entry.Collection(p => p.Vehicles);
vehicleCollection.Query()
.Include( v => v.ModelInfo )
.Load();
vehicleCollection.IsLoaded = true;
P.S。为了正确起见,这种行为在 显式加载相关实体时应用过滤器 部分的末尾有所提及:
When using the Query method it is usually best to turn off lazy loading for the navigation property. This is because otherwise the entire collection may get loaded automatically by the lazy loading mechanism either before or after the filtered query has been executed.