Where子句有多个未知条件

时间:2014-02-02 15:19:00

标签: c# .net sql-server linq asp.net-mvc-4

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

public interface IStaffInfoField
{

    // ...

    IQueryable<Staff> Filter(IQueryable<Staff> pList, string pAdditionalData);

    // ...

}

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

class NameStaffInfoField : BaseStaffInfoField
{

    // ...

    public override IQueryable<Staff> Filter(IQueryable<Staff> pList, string pAdditionalData)
    {
        return pList.Where(q => q.Name.Contains(pAdditionalData));
    }

    // ...

}

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

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

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

3 个答案:

答案 0 :(得分:3)

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

IQueryable<Staff> 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树的抽象树听起来既安全又容易。

答案 1 :(得分:2)

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

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

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

答案 2 :(得分:0)

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

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