在这里的帖子中,我学习了如何使用 Linq 的延迟执行构建动态查询。但查询实际上是使用 WHERE 条件的 AND 串联。
如何使用 OR 逻辑实现相同的查询?
由于标志枚举,查询应搜索用户名和/或Windows用户名:
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();
}
}
使用 LINQKit 的 PredicateBuilder,您可以动态构建谓词。
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
的用途:
实体框架的查询处理管道无法处理调用表达式,这就是需要对查询中的第一个对象调用 AsExpandable 的原因。通过调用 AsExpandable,可以激活 LINQKit 的表达式访问者类,该类将调用表达式替换为实体框架可以理解的更简单的构造。
或者:如果没有它,表达式将Invoke
d,这会导致 EF 中出现异常:
LINQ 表达式节点类型"调用"在 LINQ to Entities 中不受支持。
后来添加:
有一个替代谓词生成器可以执行相同的操作,但没有 Expand: http://petemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder/
这应该有帮助。
包含对多个列的查询
表格设计中似乎也存在一个基本问题(如果我错了,请纠正我)。数据库中标识符类型的用途是什么?