问题描述
我正在使用 EF6 并尝试获取对象的整个结构.问题是我正在使用继承.
I´m using EF6 and trying to eager fetch the whole structure of an object. The problem is that i´m using inheritance.
假设我有这个课程.
DbContext
DbSet<A> A { get; set; }
示例类
public class A
{
public string Id { get; set; }
public IList<Base> Bases { get; set; }
}
public abstract class Base
{
public int Id { get; set; }
public string Name { get; set; }
}
public abstract class Base1 : Base
{
public SomeClass SomeClass { get; set; }
}
public class Base2 : Base1
{
}
public class Base3 : Base1
{
public SomeOtherClass SomeOtherClass { get; set; }
}
我得到的错误是:
The Include path expression must refer to a navigation property defined on the type.
Use dotted paths for reference navigation properties and the Select operator for collection navigation properties.
为什么它不适用于以下内容?
Why doesn´t it work with the following ?
public IEnumerable<A> GetAll(string id)
{
return _ctx.A
.Include(x => x.Bases.OfType<Base1>().Select(y=>y.SomeClass))
.Where(x => x.Id.Equals(id)).ToList();
}
新示例
public IEnumerable<A> GetAll(string id)
{
var lists = _dbContext.A.Where(x => x.Id == id);
lists.SelectMany(a => a.Bases).OfType<Base1>().Include(e=>e.SomeClass).Load();
lists.SelectMany(b => b.Bases).OfType<Base3>().Include(e => e.SomeOtherClass).Load();
return lists;
}
添加了一个似乎可行的新示例.
Added a new example that seems to work.
推荐答案
简而言之,开箱即用是不可能的.
Shortly, it's not possible out of the box.
我可以建议的唯一解决方法是具体化主查询结果,然后使用与主查询相同的过滤器执行几个 OfType
查询以及必要的 Includes
,然后依赖 EF 导航属性修复.
The only workaround I can suggest is to materialize the master query result, then execute several OfType
queries with the necessary Includes
using the same filter as the master query, and rely on EF navigation property fixup.
它需要 Base
类中的反向导航属性:
It requires an inverse navigation property in the Base
class:
public abstract class Base
{
// ...
public A A { get; set; }
}
然后你可以使用这样的东西:
Then you can use something like this:
public IEnumerable<A> GetAll(string id)
{
var a = _ctx.A.Where(x => x.Id == id).ToList();
_ctx.Base.OfType<Base1>().Include(e => e.SomeClass).Where(e => e.A.Id == id).Load();
_ctx.Base.OfType<Base3>().Include(e => e.SomeOtherClass).Where(e => e.A.Id == id).Load();
return a;
}
同样的想法可以在不使用反向导航属性的情况下使用,但使用返回的基本 ID 作为过滤器:
The same idea can be used w/o inverse navigation property but with using the returned base Ids as filter:
public IEnumerable<A> GetAll(string id)
{
var a = _ctx.A.Include(e => e.Bases)
.Where(x => x.Id == id).ToList();
var baseIds = a.SelectMany(e => e.Bases.OfType<ModelA.Base1>().Select(b => b.Id));
db.Base.OfType<Base1>().Include(e => e.SomeClass)
.Where(e => baseIds.Contains(e.Id)).Load();
baseIds = a.SelectMany(e => e.Bases.OfType<Base3>().Select(b => b.Id));
db.Base.OfType<Base3>().Include(e => e.SomeOtherClass)
.Where(e => baseIds.Contains(e.Id)).Load();
return a;
}
这篇关于EF Eager 获取派生类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!