EF:热切地包括单场

时间:2018-05-07 10:58:12

标签: c# entity-framework eager-loading

我的数据库中有一个Object,其中有一个对象OwnerOwner有一个字符串NameObject还包含对象Details

我需要ObjectDetailsOwner.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会导致数据库查询。

有什么想法吗?

2 个答案:

答案 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});

它返回一个新的objectObject设置为选定的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)时,您已经可以看到此行为。