我有以下课程(过度简化):
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
所在的Image
而Image
不是Private
(同时急切地加载一个属性) Image
)。尝试执行此操作但不起作用的示例:
var tags = context.Tags
.Include("Content.Author")
.Include("Person")
.Where(t => !((Image)t.Content).Private);
我收到以下错误:
无法将“内容”类型转换为“图片”类型。 LINQ to Entities仅支持转换EDM原语或枚举类型。
删除了Where
子句:
指定的包含路径无效。 EntityType'Content'不会声明名为'Author'的导航属性。
我需要什么样的查询和/或模型架构更改才能完成此方法?
答案 0 :(得分:6)
您可以通过以下方式在Where
子句中编写过滤器:
.Where(t => t.Content is Image && !(t.Content as Image).Private)
然而,更大的问题是Include
部分。 Author
属性仅对派生类型Image
存在,但Include
将尝试加载基类型Content
(没有Author
属性)因为这是Content
中导航属性Tag
的类型。你不能在这里使用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.Author
和Person
属性(,好像您已使用Include
加载了导航属性。)
BTW:请求包含派生类型的导航属性的功能here on UserVoice。它与您的情况不完全相同,但在评论部分中甚至是针对您的情况的请求。
答案 1 :(得分:-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; }
}
私人似乎不是一个好名字,因为它与公共或私人声明冲突。