摘要:[原文作者]:Jonathan Aneja
[原文链接]:Implementing Dynamic Searching Using LINQ
在数据绑定应用程序中,一个比较常见的需求是:在程序运行时,用户能够使用任何字段的组合,动态构造条件进行查询。例如,在以下程序的查询功能中,用户可以任意组合多个列上定义的条件,并查询出符合条件的所有记录:
就像上图一样,通过各种数据源绑定,LINQ可以写出很强大的查询语句,例如,我们可以使用以下语句来查找指定的装运时间范围内,送到指定国家的所有订单:
Dim query = From order In db.Orders _
Where order.ShipCountry = txtCountry.Text _
And order.ShippedDate >= dtpStartDate.Value _
And order.ShippedDate <= dtpEndDate.Value
这很容易在编译时实现,但如果我们需要查询的是订单时间范围而不是装运时间范围呢?这种情况我们需要编写一个使用 order.OrderDate的查询。在运行时,动态生成一条这样的SQL语句不是一件难事,但如果用 LINQ应该怎么做呢? LINQ需要我们在编译时指定条件才能构造查询吗? 很幸运,答案是不,通过表达式树 API(Expression Tree API) 和表达式编译器(Expression Compiler),LINQ 支持在运行时构造动态查询.
在 Visual Studio 2008中,任何有效的VB表达式可表示为一个表达式树(Expression Tree)。 我们要做的是创建一个Expression Tree来表示该用户的条件,然后将它传递给LINQ to SQL[注①]来转换成SQL。
因此,上面 的Where子句可以写成这样:
Dim p = Expression.Parameter(GetType(Order),"")
Dim order = GetType(Order).GetProperty("ShipCountry")
Dim expr = Expression.Equal(Expression.PropertyOrField(p,order.Name),Expression.Constant("Germany"))
Dim predicate = Expression.Lambda(Of Func(Of Order,Boolean))(expr,New ParameterExpression() {p})
到目前为止,我们只完成了其中1/3的Where子句,为了动态构造一个Where子句而去写12行代码显得太啰嗦了!我会去写一个CreateCondition 的扩展方法,这个方法可以让我构造出Expression tree,而只需要用一行简单的代码就行了,参见:
Dim condition1 = db.Orders.CreateCondition("ShipCountry",Compare.Equal,"Germany")
对于ShippedDate的日期查询条件,我们可以使用下面的startDate 和endDate:
Dim startDate?= #1/1/1997#
Dim endDate?= #1/31/1997#
Dim condition2 = db.Orders.CreateCondition("ShippedDate",Compare.GreaterThanOrEqual,startDate)
Dim condition3 = db.Orders.CreateCondition("ShippedDate",Compare.LessThanOrEqual,endDate)
(注: 在Visual Studio 目录有一个叫DynamicQuery的项目,里面有更详细的应用).
注意到我们为第一个条件传入一个字符串”Germany”,后两个传入了可空类型的日期;因为CreateCondition是一个泛型方法,可以根据传入的参数推断出具体类型.我们现在需要把这几个条件集合成一个条件.
Dim c = Condition.Combine(condition1,Compare.And,condition2,condition3)
或者可以利用操作符重载写成这样(和上面的效果一样):
Dim c = condition1 And condition2 And condition3
好了,我们已经构造好了查询条件,让我们筛选出所需数据吧.
'Filter out all......[
阅读全文]