[转贴]Linq之动态查询

时间:2021-12-16 10:47:02

最近写Linq碰到一个问题,
就是如果要写一个查询系统,这个系统里面有很多TextBox可以填,
然后捞出符合各个字段的数据。

在SQL查询的时候还满方便的,用字符串连连连就可以了,
( 也就是sqlStr += "or name like '%sanc%' " )

那在Linq的话呢,就完全没有办法可以用连连连的方法QQ
后来和GOOGLE祷告后,GOOGLE告诉我目前有三种方法可以处理。

第一是出自MS的Linq Dynamic Query
Library
但听说一堆问题,就懒得去试了。
第二是自己写表达式树,也就是建立QueryBuilder
好吧,我有空会再找时间研究看看QB
第三则是由有名的C# In a Nutshell作者写的一个Library
( 其实满想读他写的书的,但是全英文....光看这篇,就懒了=
= )

总之,最后用了第三个方案,因为真的很方便,也很直觉。
要扩充或是移除,都很方便。

他给的第一个范例是这样,这个范例没用到什么技巧,
反正直接就可以用了。

1

2

3

4

5

6

7

8

9

10

11

IQueryable SearchProducts (params string[] keywords)

{

IQueryable query = dataContext.Products;

foreach (string keyword in keywords)

{

string temp = keyword;

query = query.Where (p => p.Description.Contains
(temp));

}

return query;

}

这个的功能很简单,假设你送进去,"可乐"、"畅快",
他就会把在Products的Description(描述)里面有"可乐"和"畅快"这两个关键词
的内容捞出来,也就是用and的方法。

但是,我们常常需要用到or方法,例如要查询"可乐"、"雪碧"。
那在用这种查询方法,就没办法查的到了....
( 不可能会出现一种可乐是雪碧口味的吧= =)

ok~所以作者提出了另外一种方法,也就是使用了PredicateBuilder

1

2

3

4

5

6

7

8

9

10

11

IQueryable SearchProducts (params string[] keywords)

{

var predicate = PredicateBuilder.False();

foreach (string keyword in keywords)

{

string temp = keyword;

predicate = predicate.Or (p
=> p.Description.Contains (temp));

}

return dataContext.Products.Where (predicate);

}

用Or方法,就可以用or来查询"可乐"和"雪碧"。
赞吧!!果然是神人级的。

但是看到这边,不要马上贴上去使用阿~@@~
因为最重要最重要的关键是
我们还没有PredicateBuilder这个类别阿。

这里有两个方法可以使用这个类别。
一、去作者网站下载LinqKit
二、去作者网站将PredicateBuilder的程序代码复制贴上
( 两个都够简单吧= = )

最后,要补充一下,
如果是使用Linq to Entity的话,要把程序代码的最后一行改为

1

return objectContext.Products.AsExpandable().Where
(predicate);

也就是如下程序代码。

1

2

3

4

5

6

7

8

9

10

11

IQueryable SearchProducts (params string[] keywords)

{

var predicate = PredicateBuilder.False();

foreach (string keyword in keywords)

{

string temp = keyword;

predicate = predicate.Or (p
=> p.Description.Contains (temp));

}

return objectContext.Products.AsExpandable().Where (predicate);

}

另外,如果要查名子、描述、发行公司等等
很多TextBox的话,怎么办呢?
就改成这样。

1

2

3

4

var predicate = PredicateBuilder.False();

predicate = predicate.Or(p => p.name.Contains(要查询的));

predicate = predicate.Or(p => p.Description.Contains
(要查询的));

objectContext.Products.AsExpandable().Where
(predicate);

这样扩充有没有很容易呢!?

最后,这些我都还没实验过,实验完后,我会再修改这篇文章,
将正确的讯息贴上。