Where子句有多个未知条件

我目前正在为我的公司开发员工管理系统。 字段可能会有所不同,并且会不时更改,因此我为每个字段设置了一个界面,如下所示:

public interface IStaffInfoField { // ... IQueryable Filter(IQueryable pList, string pAdditionalData); // ... } 

对于每个字段,我实现Filter方法,例如使用Name

 class NameStaffInfoField : BaseStaffInfoField { // ... public override IQueryable Filter(IQueryable pList, string pAdditionalData) { return pList.Where(q => q.Name.Contains(pAdditionalData)); } // ... } 

现在用户想要使用多个条件进行搜索,这很简单,我只需遍历列表并调用Filter 。 但是,他们还需要OR条件(例如,名称为A ,OR名称为B ,AND部门名称为C ,或年龄为30员工)。 注意:用户是最终用户,他们通过combobox和文本框输入搜索查询。

我能以某种方式修改我的模式或lambda表达式吗? 因为在整个过程中,我没有将原始列表保存为Union它的OR条件。 我认为如果我保存表达式并将其联合为OR条件将会很慢。

我现在能想到的唯一解决方案是为需要原始SQL WHERE语句的接口添加一个方法。 但是我的整个程序还没有使用纯SQL查询,现在使用它是不是很糟糕?

你可以下载Albahari的LINQKit 。 它包含一个PredicateBuilder ,除了其他有用的东西之外,它还允许您以动态的方式将LINQ表达式与OR连接起来。

 var predicate = PredicateBuilder.False(); predicate = predicate.Or(s => s.Name.Contains(data)); predicate = predicate.Or(s => s.Age > 30); return dataContext.Staff.Where(predicate); 

您还可以下载源代码并查看其实现方式。

由于您的方法返回IQueryable ,因此客户端已经可以将它用于任意复杂的查询。

 IQueryable result = xxx.Filter( .... ); result = result.Where( ... ); if ( ... ) result = result.Where( s => ( s.Age > 30 || s.Salary < 1 ) && s.Whatever == "something" ); 

IQueryable非常灵活。 当您开始枚举结果时,将评估查询树并将其转换为sql。

我只是想知道为什么你需要这个界面?! 由于您的Filter方法需要IQueryable ,这意味着客户端已经具有 IQueryable ! 如果她已经可以自己应用任意复杂的查询运算符,为什么她会调用你的Filter方法呢?

编辑:

在你的额外解释之后,如果我是你,我会创建一个简单的界面,让用户创建自己的包含OR和AND子句的查询树,并创建一个简单的函数,将用户查询树转换为linq表达式树。

换句话说,不要让最终用户在linq查询树级别工作,这太过抽象,而且太危险,不允许用户触摸代码的这种低级别层。 但是手动翻译为linq树的抽象树听起来既安全又容易。

如果您的用户是最终用户,并且他们通过UI输入条件,您可能需要查看支持IQueryable的UI控件。 Telerik有大量的预烘焙控件。 在大多数情况下,最终用户与网格进行交互,并将filter应用于列。 还有其他几家供应商做同样的事情。

第二种选择,如果您想让生活变得困难,您可以获取用户提供的输入文本,将其解析为表达式树,然后将该表达式树映射到IQueryable。 如果您不熟悉解析器,则此任务将很难实现。