实体框架代码第一个4.3 / LINQKit相关表的谓词

时间:2012-07-17 19:52:41

标签: entity-framework entity-framework-4 linq-to-entities ef-code-first

我正在使用Entity Framework 4.3.1和Code First方法。另外,我使用LinqKit以便使用PredicateBuilder。

如果我有这样的表:

位置,TimeZone(很多:1)

..我希望有类似的东西:

Expression<Func<TimeZone, bool>> pred = PredicateBuilder.True<TimeZone>();
pred = pred.And(tz => tz.TimeZoneCode == "EST");

List<Location> locations = context.Locations
    .AsExpandable().Where(pred)
    .Select(loc => loc).ToList();

这不起作用,因为谓词是为接受TimeZone而构建的,但Where()方法接收一个Location。

我可以像这样重写谓词,但我不想这样做,因为我想要一个为特定类型创建谓词的谓词工厂(我不想以这种方式使用Navigator属性):

Expression<Func<Location, bool>> pred = PredicateBuilder.True<Location>();
pred = pred.And(loc => loc.TimeZone.TimeZoneCode == "EST");

我可以使用什么语法(如果有的话)来使用第一个示例中构造的谓词,它使用TimeZone,而不是通过导航属性获取位置并遍历树(因为这不太可重复使用) )。如果有一种方法可以首先利用EF对导航属性的知识,并且能够使用作用于导航属性类型的谓词,那将是很好的。

2 个答案:

答案 0 :(得分:5)

经过大约一周的努力,我发现你实际上可以做到这一点。步骤是:

  1. 定义谓词,该谓词是内部属性的查询(subPredicate
  2. Invoke subPredicate来自另一个谓词(predicate),针对父对象的属性。
  3. 在您的Expand条款中使用{li> predicate Where

    以下是您的示例的修订代码:

    var subPredicate = PredicateBuilder.True<TimeZone>();
    subPredicate = subPredicate.And(tz => tz.TimeZoneCode == "EST");
    
    var predicate = PredicateBuilder.True<Location>();
    predicate = predicate.And(l => subPredicate.Invoke(l.TimeZone));
    
    List<Location> locations = context.Locations
        .AsExpandable().Where(pred.Expand())
        .Select(loc => loc).ToList();
    

答案 1 :(得分:2)

只是为了更新这个:事实证明这些谓词的意图是过滤主要实体。心理概念是:决定您要返回哪些实体,然后返回它们。 EF显然不是为儿童实体的这种深度谓词应用而设计的。

一个人(我不记得在哪里)提出了一个很好的观点:如果孩子们已经预先加载,你就不会期待一个部分装载的收藏品。因此,拥有一个Invoice实体是没有意义的,例如,只有一半的发票行。

我想要实现的更多的是EXISTS()或IN(),您可以说“给我所有发票,其中有产品类型的发票行'坚果'和'螺栓'”。这是可行的,但您可能必须应用LINQ或编写自己的对象。 EF开箱即用的意图是将发票交给您,然后您可能会懒洋洋地或急切地加载发票行,但不能直接从数据库中将它们用作过滤器。

我看到有些结构可以完成某些操作,但语法很快就会无法管理。

不要打市政厅。