Entity Framework 4.1 Code First - 使用 LinqKit PredicateBuilder 时忽略包含

Posted

技术标签:

【中文标题】Entity Framework 4.1 Code First - 使用 LinqKit PredicateBuilder 时忽略包含【英文标题】:Entity Framework 4.1 Code First - Include is being ignored when using LinqKit PredicateBuilder 【发布时间】:2011-09-19 18:17:51 【问题描述】:

我正在使用 Entity Framework 4.1 Code First 并且还使用 PredicateBuilder,以便我可以跨多个规范类构建谓词表达式(使用规范模式)。我能够正确构建谓词并将其应用于 DbSet,并且我得到的数据是我所期望的。但是,无论我尝试什么,它总是延迟加载。这是我如何构建谓词并应用它的一个简单示例。

IQueryable<HairColor> hairColorQuery = Context.Set<HairColor>().AsExpandable();

Expression<Func<Parent, bool>> parentPredicate = PredicateBuilder.And(PredicateBuilder.True<Parent>(), p => p.NameLast.StartsWith("V")).Expand();

Expression<Func<HairColor, bool>> hairColorPredicate = PredicateBuilder.And(PredicateBuilder.True<HairColor>(), h => h.Parents.AsQueryable().Any(parentPredicate));

HairColor[] hairColors = hairColorQuery.Where(hairColorPredicate).Include(h => h.Parents).ToArray();

就像我上面所说的,我正在取回我想要的数据,但它忽略了包含。

有人有什么想法吗?

【问题讨论】:

【参考方案1】:

可能是changing the query shape。试试这个解决方法

HairColor[] hairColors = hairColorQuery.Where(hairColorPredicate)
                                       .Select(hc => new 
                                                     
                                                         HairColor = hc,
                                                         Parents = hc.Parents // eager load
                                                     )
                                       .AsEnumerable()
                                       .Select(hc => hc.HairColor);

【讨论】:

我按照您的指示重写了查询,看起来您所做的更改是将生成的 IQueryable 从 Where 方法转换为 HairColor 的 DbQuery。但是,当我这样做时,这是有道理的。我得到一个演员表异常: 无法转换类型为“LinqKit.ExpandableQuery1[DaycareDashboard.Data.Entities.HairColor]' to type 'System.Data.Entity.Infrastructure.DbQuery1[DaycareDashboard.Data.Entities.HairColor]”的对象。 这是有道理的,因为 AsExpandable() 很可能会更改 IQueryable 的基础类型。我做了一个快速的谷歌搜索,看看 LinqKit.ExpandableQuery 是否有包含问题,但我找不到任何东西。感谢您迄今为止的帮助。还有什么想法吗? 您不必在分页之前进行投影。您可以先进行分页,然后投影出您需要的数据。只要你留在IQueryable&lt;T&gt; 空间,它应该仍然可以工作。 你就是男人!我将它移到了我的分页和排序方法所在的位置之后,它完美地工作了一个例外。虽然第一个查询运行从 HairColors 和 Parent 表中选择数据,就像您所期望的那样,但随后执行了其他查询以延迟加载子属性。我禁用了上下文的延迟加载,它停止了额外的调用,并且子集合仍在被填充。我认为这个问题得到了回答。但我对为什么会看到上述行为感兴趣?【参考方案2】:

您好,在这方面迟到了,但是在使用 LinqKits 谓词构建器时使用扩展 Include 方法时遇到了同样的问题。上一个答案中提到的问题是将 LinqKits ExpandableQuery 转换为 ObjectQuery(根据 Include 扩展的要求)会导致 null。

但是发现此链接http://petemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder/ 是一个谓词构建器,它不使用 AsExpandable 来执行搜索,因此可以在其上使用 Include 方法。虽然上面的解决方案也对我有用,但这个不同的谓词构建器让我的代码更简洁/更一致

【讨论】:

谢谢!最初的项目现在已经投入生产,但我开始更多地了解如何构建表达式树,这个实现可能非常有用。 @DylanVester - 您可能需要考虑交换这个答案框。重新排列您的特定查询是一种解决方法,但在来自该链接的通用谓词构建器中绝对是更通用的解决方法。 同意,我已经交换了答案,因为这是第一个并且有更多的赞成票。

以上是关于Entity Framework 4.1 Code First - 使用 LinqKit PredicateBuilder 时忽略包含的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework 4.1Code First 连接到 Sql Server 2005

Entity Framework 4.1 Code First 关系中的更改通常不需要

Entity Framework 4.1 Code First - 插入非主键时自动递增字段

我应该如何在 MVC3 中使用 Code First Entity Framework (4.1) 声明外键关系?

virtual 关键字在 Entity Framework 4.1 POCO Code First 中可以产生啥影响?

Entity Framework 4.1 Code First,一对一,一个表连接到复合键的单个键字段