EF代码优先 - 渴望加载和过滤子类属性(继承)

Alb*_*ori 2 c# inheritance entity-framework ef-code-first

我有以下课程(过于简化):

public class Person
{
    public int ID { get; set; }
}
public class Content
{
    public int ID { get; set; }
}
public class Image : Content
{
    public bool Private { get; set; }
    public Person Author { get; set; }
}
public class Tag
{
    public int ID { get; set; }
    public Content Content { get; set; }
    public Person Person { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我想获得所有TagsContentImageImage不是Private(而急切地加载的属性Image).尝试执行此操作但不起作用的示例:

var tags = context.Tags
    .Include("Content.Author")
    .Include("Person")
    .Where(t => !((Image)t.Content).Private);
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

无法将类型"内容"转换为"图像"类型.LINQ to Entities仅支持转换EDM原语或枚举类型.

Where删除该条款:

指定的包含路径无效.EntityType'Content'不会声明名为'Author'的导航属性.

我需要什么样的查询和/或模型架构更改才能完成此方法?

Sla*_*uma 6

您可以Where通过以下方式在子句中编写过滤器:

.Where(t => t.Content is Image && !(t.Content as Image).Private)
Run Code Online (Sandbox Code Playgroud)

然而,更大的问题是这个Include部分.该Author属性只存在派生型Image,但Include将尝试加载基本类型Content(它不具有Author属性),因为这是导航属性的类型ContentTag.你不能Include在这里使用.

您可以尝试将查询重写为投影:

var tags = context.Tags
    .Where(t => t.Content is Image && !(t.Content as Image).Private)
    .Select(t => new
    {
        Tag = t,
        Image = t.Content as Image, // possibly this line is not needed
        Author = (t.Content as Image).Author,
        Person = t.Person
    })
    .AsEnumerable()
    .Select(x => x.Tag)
    .ToList();
Run Code Online (Sandbox Code Playgroud)

只要您不要禁用更改跟踪(带AsNoTracking为例)EF应该自动把对象图在一起,使得加载标签具有填充Content,Content.AuthorPerson财产(就好像你曾与装载的导航属性Include).

BTW:在UserVoice上请求包含派生类型的导航属性的功能.它与您的情况不完全相同,但在评论部分中甚至是针对您的场景的请求.