我的数据库中有一个Object
,其中有一个对象Owner
。 Owner
有一个字符串Name
。 Object
还包含对象Details
。
我需要Object
,Details
和Owner.Name
。我想阻止加载整个Owner
对象(如详细here),我只想要一个数据库查询。
我试过了:
DataContext.Objects.Select(o => new { Object = o, OwnerName= o.Owner.Name })
.Include(o => o.Object.Details);
但它会抛出:
System.InvalidOperationException:'查询的结果类型既不是EntityType,也不是具有实体元素类型的CollectionType。只能为具有这些结果类型之一的查询指定包含路径。
还尝试在Include
之前调用Select
:
var d = DataContext.Objects.Include(o => o.Details)
.Select(o => new { Object = o, OwnerName= o.Owner.Name });
但这忽略了Include
,即。访问d.Details
会导致数据库查询。
有什么想法吗?
答案 0 :(得分:0)
这个应该这样做(尽管Details
被加载到一个单独的属性中来纠正@ Flatter的评论):
DataContext.Objects
.Include(o => o.Owner>)
.Include(o => o.Details)
.Select(o => new {Object = o,
OwnerName = o.Owner.Name,
Details = o.Details});
它返回一个新的object
,Object
设置为选定的Object
(如果可以,请考虑重命名,非常令人困惑),并填充OwnerName
所有者表没有加载整个所有者。它还会将Details
填充为单独的属性,因为Select
会忽略Include
。
我说它“应该”有效,因为如果没有看到你的表结构,我必须根据你对事物连接方式的描述进行猜测。
答案 1 :(得分:0)
您正在触及EF中确实存在的问题。
问题在于EF如何处理数据加载。它加载对象的所有标量属性,但不加载导航属性。
Include
通过告知EF 还包含指定的导航属性(包含其所有标量属性)来影响此行为
然后我们到达Select
。使用此功能时,您实际上是要提供要检索的已修复列列表。这会覆盖加载所有标量属性的默认行为,这可能会覆盖您添加的Include
语句。
最简单的解决方案是明确告诉EF检索详细信息:
var d = DataContext.Objects.Include(o => o.Details)
.Select(o => new {
Object = o,
ObjectDetails = o.Details,
OwnerName= o.Owner.Name
});
另外,由于Select
明确说明EF需要检索哪些列,因此您不再需要Include
语句。
在没有实际调用o.Owner.Name
的情况下检索Include(o => o.Owner)
时,您已经可以看到此行为。