Linq to Entities 中的动态 where 子句 (OR)
Posted
技术标签:
【中文标题】Linq to Entities 中的动态 where 子句 (OR)【英文标题】:Dynamic where clause (OR) in Linq to Entities 【发布时间】:2013-01-15 07:10:03 【问题描述】:在here 的帖子中,我学习了如何使用 Linq 的延迟执行来构建动态查询。但查询实际上是使用 WHERE 条件的 AND 连接。
如何使用 OR 逻辑实现相同的查询?
由于 Flags 枚举,查询应该搜索 Username、WindowsUsername 或 both:
public User GetUser(IdentifierType type, string identifier)
using (var context = contextFactory.Invoke())
var query = from u in context.Users select u;
if (type.HasFlag(IdentifierType.Username))
query = query.Where(u => u.Username == identifier);
if (type.HasFlag(IdentifierType.Windows))
query = query.Where(u => u.WindowsUsername == identifier);
return query.FirstOrDefault();
【问题讨论】:
【参考方案1】:使用LINQKit's PredicateBuilder 你可以build predicates dynamically。
var query = from u in context.Users select u;
var pred = Predicate.False<User>();
if (type.HasFlag(IdentifierType.Username))
pred = pred.Or(u => u.Username == identifier);
if (type.HasFlag(IdentifierType.Windows))
pred = pred.Or((u => u.WindowsUsername == identifier);
return query.Where(pred.Expand()).FirstOrDefault();
// or return query.AsExpandable().Where(pred).FirstOrDefault();
这就是Expand
的用途:
Entity Framework 的查询处理管道无法处理调用表达式,这就是您需要在查询中的第一个对象上调用 AsExpandable 的原因。通过调用 AsExpandable,您可以激活 LINQKit 的表达式访问者类,该类将调用表达式替换为 Entity Framework 可以理解的更简单的构造。
或者:没有它的表达式是Invoke
d,这会导致EF中的异常:
LINQ to Entities 不支持 LINQ 表达式节点类型“Invoke”。
后期添加:
有一个替代的谓词构建器可以做同样的事情,但没有展开:http://petemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder/
【讨论】:
太棒了!完美运行! 是否有不需要第三方库的选项? (我希望避免我公司因使用 3rd 方库而产生的行政麻烦) @Zarepheth 这个“通用谓词构建器”几乎不是第三方库。它是您自己的代码库的一部分。只需在评论中给这个家伙学分:) 我必须在此解决方案中使用LINQKit
库 - 或点击第二个链接到另一个选项。但是,我继续搜索并安装了满足我需求的Microsoft.Linq.Dynamic
NuGet 包。 (微软的免费赠品通常是允许的,无需额外的繁文缛节)。
我应该关注第二个链接;这是一个相对较小的类,我可以复制到我的代码中。哦,好吧,我现在有 Microsoft 软件包。【参考方案2】:
这应该会有所帮助..
Contains Query on multiple columns
表的设计似乎也存在根本问题(如果我错了,请纠正我)。数据库中 IdentifierType 的用途是什么?
【讨论】:
IdentifierType 不是数据库的一部分。它只是告诉函数哪些列应该包含在 WHERE 条件中。以上是关于Linq to Entities 中的动态 where 子句 (OR)的主要内容,如果未能解决你的问题,请参考以下文章
使用 Linq to Entities (EF6) 动态选择列名
在CQ中使用动态表达式在LINQ to Entities中使用INT列