我正在使用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对导航属性的知识,并且能够使用作用于导航属性类型的谓词,那将是很好的。
答案 0 :(得分:5)
经过大约一周的努力,我发现你实际上可以做到这一点。步骤是:
subPredicate
)Invoke
subPredicate
来自另一个谓词(predicate
),针对父对象的属性。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开箱即用的意图是将发票交给您,然后您可能会懒洋洋地或急切地加载发票行,但不能直接从数据库中将它们用作过滤器。
我看到有些结构可以完成某些操作,但语法很快就会无法管理。
不要打市政厅。