Nat*_*ers 70 entity code-first entity-framework-4.1 entity-framework-4.3
有没有办法装饰你的POCO类来自动加载子实体而不必Include()每次加载时都使用它们?
假设我有一辆Class Car,车轮,门,发动机,保险杠,Windows,排气等的复杂类型属性.在我的应用程序中,我需要从我的DbContext 20个不同的地方加载我的汽车,不同的查询,等等.不希望每次我想加载我的汽车时都要指定我想要包含所有属性.
我想说
List<Car> cars = db.Car
.Where(x => c.Make == "Ford").ToList();
//NOT .Include(x => x.Wheels).Include(x => x.Doors).Include(x => x.Engine).Include(x => x.Bumper).Include(x => x.Windows)
foreach(Car car in cars)
{
//I don't want a null reference here.
String myString = car.**Bumper**.Title;
}
Run Code Online (Sandbox Code Playgroud)
我可以以某种方式装饰我的POCO类或我的OnModelCreating()或在EF中设置一个配置,它会告诉它在我装车时加载我汽车的所有部件吗?我想热切地这样做,所以我的理解是让我的导航属性变得虚拟.我知道NHibernate支持类似的功能.
只是想知道我是否遗漏了什么.提前致谢!
干杯,
弥敦道
我喜欢下面的解决方案,但我想知道我是否可以嵌套对扩展方法的调用.例如,假设我与Engine有类似的情况,它有很多部分,我不希望包含在任何地方.我可以这样做吗?(我还没有找到一种工作方式).这样,如果以后我发现Engine需要FuelInjectors,我只能在BuildEngine中添加它,而不必在BuildCar中添加它.此外,如果我可以嵌套调用,如何将调用嵌套到集合中?想从我的BuildCar()中为每个轮子调用BuildWheel()?
public static IQueryable<Car> BuildCar(this IQueryable<Car> query) {
return query.Include(x => x.Wheels).BuildWheel()
.Include(x => x.Doors)
.Include(x => x.Engine).BuildEngine()
.Include(x => x.Bumper)
.Include(x => x.Windows);
}
public static IQueryable<Engine> BuildEngine(this IQueryable<Engine> query) {
return query.Include(x => x.Pistons)
.Include(x => x.Cylendars);
}
//Or to handle a collection e.g.
public static IQueryable<Wheel> BuildWheel(this IQueryable<Wheel> query) {
return query.Include(x => x.Rim)
.Include(x => x.Tire);
}
Run Code Online (Sandbox Code Playgroud)
这是另一个非常相似的线程,以防它在这种情况下对其他任何人有帮助,但它仍然无法处理能够对扩展方法进行nexted调用.
Lad*_*nka 61
不,你不能在映射中做到这一点.典型的解决方法是简单的扩展方法:
public static IQueryable<Car> BuildCar(this IQueryable<Car> query) {
return query.Include(x => x.Wheels)
.Include(x => x.Doors)
.Include(x => x.Engine)
.Include(x => x.Bumper)
.Include(x => x.Windows);
}
Run Code Online (Sandbox Code Playgroud)
现在,每当您想要查询Car所有关系时,您将只执行以下操作:
var query = from car in db.Cars.BuildCar()
where car.Make == "Ford"
select car;
Run Code Online (Sandbox Code Playgroud)
编辑:
你无法以这种方式嵌套.包含适用于您正在使用的核心实体 - 该实体定义查询的形状,因此在您通话后Include(x => Wheels)仍在使用IQueryable<Car>,您无法调用扩展方法IQueryable<Engine>.你必须再次开始Car:
public static IQueryable<Car> BuildCarWheels(this IQuerable<Car> query) {
// This also answers how to eager load nested collections
// Btw. only Select is supported - you cannot use Where, OrderBy or anything else
return query.Include(x => x.Wheels.Select(y => y.Rim))
.Include(x => x.Wheels.Select(y => y.Tire));
}
Run Code Online (Sandbox Code Playgroud)
并且您将以这种方式使用该方法:
public static IQueryable<Car> BuildCar(this IQueryable<Car> query) {
return query.BuildCarWheels()
.Include(x => x.Doors)
.Include(x => x.Engine)
.Include(x => x.Bumper)
.Include(x => x.Windows);
}
Run Code Online (Sandbox Code Playgroud)
用法不会调用,Include(x => x.Wheels)因为当您请求其嵌套实体的预先加载时,它应该自动添加.
注意由这种复杂的急切加载结构产生的复杂查询.它可能导致非常差的性能以及从数据库传输的大量重复数据.
Ado*_*Ado 14
从 EF Core 6 开始,有一个 AutoInclude 方法可以配置是否应自动包含导航。
这可以在 DbContext 类中的 OnModelCreation 方法中完成:
modelBuilder.Entity<Car>().Navigation(e => e.Wheels).AutoInclude();
Run Code Online (Sandbox Code Playgroud)
这将在运行以下查询时加载Weelsfor every 。Car
var cars = dbContext.Cars.ToList();
Run Code Online (Sandbox Code Playgroud)
请参阅自动包含导航的模型配置
遇到了同样的问题,并看到了提到Include属性的另一个链接。我的解决方案假设您创建了一个名为IncludeAttribute. 使用以下扩展方法和实用方法:
public static IQueryable<T> LoadRelated<T>(this IQueryable<T> originalQuery)
{
Func<IQueryable<T>, IQueryable<T>> includeFunc = f => f;
foreach (var prop in typeof(T).GetProperties()
.Where(p => Attribute.IsDefined(p, typeof(IncludeAttribute))))
{
Func<IQueryable<T>, IQueryable<T>> chainedIncludeFunc = f => f.Include(prop.Name);
includeFunc = Compose(includeFunc, chainedIncludeFunc);
}
return includeFunc(originalQuery);
}
private static Func<T, T> Compose<T>(Func<T, T> innerFunc, Func<T, T> outerFunc)
{
return arg => outerFunc(innerFunc(arg));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
38150 次 |
| 最近记录: |