最近写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); |
这样扩充有没有很容易呢!?
最后,这些我都还没实验过,实验完后,我会再修改这篇文章, 将正确的讯息贴上。