entity framework – 有没有一种方法来自动加载没有包含()的子实体?
有没有办法装饰你的POCO类来自动加载子实体,而不必在每次加载时使用Include()
?
说我有一个类车,车轮,门,引擎,保险杠,窗户,排气等复杂types的属性,在我的应用程序,我需要从我的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; }
我可以以某种方式装饰我的POCO类,或者在我的OnModelCreating()
或者在EF中设置一个configuration,告诉它在装载我的汽车时只装载我的汽车的所有部件? 我希望这样做,所以我的理解是,使我的导航属性虚拟出来。 我知道NHibernate支持类似的function。
只是想知道我是否错过了一些东西。 提前致谢!
干杯,
弥敦道
我喜欢下面的解决scheme,但是想知道是否可以将调用嵌套到扩展方法。 例如,说我有一个类似的情况与发动机,它有很多部分,我不想包括到处。 我可以做这样的事吗? (我还没有find一种方法,这个工作呢)。 这样,如果以后我发现引擎需要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 eg public static IQueryable<Wheel> BuildWheel(this IQueryable<Wheel> query) { return query.Include(x => x.Rim) .Include(x => x.Tire); }
这是另一个非常相似的线程,以防止在这种情况下对其他任何人有帮助,但是仍然无法处理对扩展方法的中断调用。
entity frameworkLINQ查询包含()多个子实体
不,你不能在地图上做到这一点 。 典型的解决方法是简单的扩展方法:
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); }
现在,每当你想要用所有的关系来查询Car
,你只需要做:
var query = from car in db.Cars.BuildCar() where car.Make == "Ford" select car;
编辑:
你不能以这种方式嵌套调用。 包含您正在使用的核心实体的作品 – 该实体定义查询的形状,因此在调用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)); }
你会用这种方法:
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); }
这个用法不会调用Include(x => x.Wheels)
因为当你请求加载它的嵌套实体时,它应该被自动添加。
注意由这种复杂的加载结构产生的复杂查询。 这可能会导致很差的性能和大量从数据库传输的重复数据 。
有这个相同的问题,看到提到一个Include
属性的其他链接。 我的解决scheme假定您创build了一个名为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)); }