C# Linq to实体中的动态where子句(或)

C# Linq to实体中的动态where子句(或),c#,linq,entity-framework,linq-to-entities,where-clause,C#,Linq,Entity Framework,Linq To Entities,Where Clause,在这篇文章中,我学习了如何使用Linq的延迟执行来构建动态查询。但是查询实际上是使用WHERE条件的和串联 如何使用OR逻辑实现相同的查询? 由于标志枚举,查询应搜索用户名、WindowsUsername或两者: public User GetUser(标识符类型,字符串标识符) { 使用(var context=contextFactory.Invoke()) { var query=来自上下文中的u。用户选择u; if(type.HasFlag(IdentifierType.Username

在这篇文章中,我学习了如何使用Linq的延迟执行来构建动态查询。但是查询实际上是使用WHERE条件的串联

如何使用OR逻辑实现相同的查询?

由于标志枚举,查询应搜索用户名、WindowsUsername或两者:

public User GetUser(标识符类型,字符串标识符)
{
使用(var context=contextFactory.Invoke())
{
var query=来自上下文中的u。用户选择u;
if(type.HasFlag(IdentifierType.Username))
query=query.Where(u=>u.Username==标识符);
if(type.HasFlag(IdentifierType.Windows))
query=query.Where(u=>u.WindowsUsername==标识符);
返回query.FirstOrDefault();
}
}
这应该会有帮助

表的设计似乎也存在一个基本问题(如果我错了,请纠正我)。数据库中IdentifierType的用途是什么?

使用PredicateBuilder,您可以

var query=来自上下文中的u。用户选择u;
var pred=Predicate.False();
if(type.HasFlag(IdentifierType.Username))
pred=pred.Or(u=>u.Username==标识符);
if(type.HasFlag(IdentifierType.Windows))
pred=pred.Or((u=>u.WindowsUsername==标识符);
返回query.Where(pred.Expand()).FirstOrDefault();
//或者返回query.AsExpandable().Where(pred.FirstOrDefault();
这就是展开的
的作用:

实体框架的查询处理管道无法处理调用表达式,这就是为什么需要对查询中的第一个对象调用AsExpandable。通过调用AsExpandable,可以激活LINQKit的expression visitor类,该类使用实体框架可以理解的更简单的构造替换调用表达式

或者:如果没有它,表达式是
Invoke
d,这会导致EF中出现异常:

LINQ to实体中不支持LINQ表达式节点类型“Invoke”

以后添加:


还有一种替代的谓词生成器可以做同样的事情,但不需要扩展:

这是惊人的东西!工作非常完美!有没有不需要第三方库的选项?(我更愿意避免我公司在使用第三方库时的管理麻烦)@Zarephth这个“通用谓词生成器”它几乎不是第三方库。它是您自己代码库的一部分。只需在注释中给这个家伙评分:)我必须将
LINQKit
库用于此解决方案-或者按照第二个链接转到另一个选项。但是,我继续搜索并安装了
Microsoft.Linq.Dynamic
NuGet软件包,它满足了我的需要。(微软的免费赠品通常是允许的,没有额外的繁文缛节);这是一个相对较小的类,我可以复制到我的代码中。哦,好吧,我现在有了微软的软件包。IdentifierType不是数据库的一部分。它只是告诉函数WHERE条件中应该包含哪些列。
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();