2

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

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; }
}

我想得到所有在Tags哪里Content是一个ImageImage不是Private(同时急切地加载一个属性Image)。尝试执行此操作但不起作用的示例:

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

我收到以下错误:

无法将类型“内容”转换为类型“图像”。LINQ to Entities 仅支持转换 EDM 基元或枚举类型。

Where删除了该子句:

指定的包含路径无效。EntityType“内容”未声明名为“作者”的导航属性。

我需要什么样的查询和/或模型模式更改才能完成这种方法?

4

2 回答 2

6

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

.Where(t => t.Content is Image && !(t.Content as Image).Private)

但是,更大的问题是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();

只要您不禁用更改跟踪(AsNoTracking例如),EF 应该自动将对象图放在一起,以便加载的标签具有填充的Content,Content.AuthorPerson属性(就像您已使用 加载导航属性一样Include)。

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

于 2013-03-18T19:21:21.147 回答
-1

尝试将类定义更改为...

class Person
{
  public int ID { get; set; }
}

class Content
{
  public int ID { get; set; }
}

class Image : Content
{
  public bool IsPrivate { get; set; }   
  public virtual Person Author { get; set; }
}

class Tag
{
public int ID { get; set; }
public Content Content { get; set; }
public Person Person { get; set; }
}

私有似乎不是一个好名称,因为它与公共或私有声明冲突。

于 2013-03-17T09:21:59.700 回答