我目前正在为我的公司开发员工管理系统。字段可能会有所不同并且会不时更改,因此我为每个字段设置了一个界面,如下所示:
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查询,现在使用它是不是很糟糕?
答案 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。如果您不熟悉解析器,则此任务将很难实现。