从LINQ实例解析LINQ的另类用法,解决多条件组合问题

本文介绍了一种使用.NET 3.5的LINQ进行多条件组合查询的方法,通过定义枚举类型来组织查询条件,并利用Expression.And方法实现复杂查询条件的组合。

YiDaoWang.com这个项目准备功能改版,师兄吩咐:尽可能地做到万般皆LINQ,所以很多东西都要从存储过程搬过来..
昨天写评价功能的时候,碰到个多条件叠加组合的问题,其需求如下:

多种查询评价的条件:
1.查询类型:收到的评价_买家给我的评价,收到的评价_卖家给我的评价,给出的评价_我给买家的评价,给出的评价_我给卖家的评价

ContractedBlock.gifExpandedBlockStart.gifCode
1 public enum OpinionSearchType
2 {
3     收到的评价_买家给我的评价 = 0,
4     收到的评价_卖家给我的评价 = 1,
5     给出的评价_我给买家的评价 = 2,
6     给出的评价_我给卖家的评价 = 3
7 }
2.评价类型:全部,好评,中评,差评
ContractedBlock.gifExpandedBlockStart.gifCode
1 public enum OpinionType
2 {
3     全部 = 0,
4     好评 = 1,
5     中评 = 2,
6     差评 = 3
7 }
3.评价查询时间:全部,一个星期内,一个月以内,六个月以内,六个月以外
ContractedBlock.gifExpandedBlockStart.gifCode
1 public enum OpinionTime
2 {
3     全部 = 0,
4     一个星期内 = 1,
5     一个月以内 = 2,
6     六个月以内 = 3,
7     六个月以外 = 4
8 }

 

由于缓存的需要,要把Expression完成之后再传到接口那边获取相应的List<评价意见>.按照这样的看的话,
总共3个条件, 13个子条件, 排列组合之后, 会有80种的组合. - - 真的一个个组合去写的话,还真是累死人了..

左思右想,最好的方法就是把3个条件都拆开来,完成不同的Expression,到最后再把三个条件组合在一起成为一个新的Expression.
网上找到的比较都只是单条件的Parameter, 查了MSDN,才知道有个Expression.And(left, right)可以完成我的需求.
利用.net3.5的扩展方法写成了一个组合Expression的方法,再重载了几个多参数的表达式,如下:

ContractedBlock.gifExpandedBlockStart.gifCode
 1 #region 表达式
 2 
 3 public static Expression ContactExpressions(this Expression exp, params Expression[] exps) {
 4     foreach (var e in exps) {
 5         if (null == e) continue;
 6         exp = Expression.And(exp, e);
 7     }
 8     return exp;
 9 }
10 
11 public static Expression<Func<T>> ContactExpressions<T>(this Expression exp, params Expression[] exps) {
12     foreach (var e in exps) {
13         if (null == e) continue;
14         exp = Expression.And(exp, e);
15     }
16     return (Expression<Func<T>>)exp;
17 }
18 
19 public static Expression<Func<T1, T>> ContactExpressions<T1, T>(this Expression exp, params Expression[] exps) {
20     foreach (var e in exps) {
21         if (null == e) continue;
22         exp = Expression.And(exp, e);
23     }
24     return (Expression<Func<T1, T>>)exp;
25 }
26 
27 public static Expression<Func<T1, T2, T>> ContactExpressions<T1, T2, T>(this Expression exp, params Expression[] exps) {
28     foreach (var e in exps) {
29         if (null == e) continue;
30         exp = Expression.And(exp, e);
31     }
32     return (Expression<Func<T1, T2, T>>)exp;
33 }
34 
35 public static Expression<Func<T1, T2, T3, T>> ContactExpressions<T1, T2, T3, T>(this Expression exp, params Expression[] exps) {
36     foreach (var e in exps) {
37         if (null == e) continue;
38         exp = Expression.And(exp, e);
39     }
40     return (Expression<Func<T1, T2, T3, T>>)exp;
41 }
42 
43 #endregion

有了这几个方法,原本的需求就可以迎刃而解了:

ContractedBlock.gifExpandedBlockStart.gifCode
 1 Expression<Func<split_Opinion, bool>> expSearchType = null;
 2 Expression<Func<split_Opinion, bool>> expOpinionType = null;
 3 Expression<Func<split_Opinion, bool>> expOpinionTime = null;
 4 
 5 switch (searchType) {
 6     case OpinionSearchType.给出的评价_我给买家的评价:
 7         expSearchType = Y => Y.UserID == userID && !Y.IsSeller;
 8         break;
 9     case OpinionSearchType.给出的评价_我给卖家的评价:
10         expSearchType = Y => Y.UserID == userID && Y.IsSeller;
11         break;
12     case OpinionSearchType.收到的评价_买家给我的评价:
13         expSearchType = Y => Y.ToUserID == userID && !Y.IsSeller;
14         break;
15     case OpinionSearchType.收到的评价_卖家给我的评价:
16         expSearchType = Y => Y.ToUserID == userID && !Y.IsSeller;
17         break;
18 }
19 
20 switch (opinType) {
21     case OpinionType.好评:
22         expOpinionType = Y => Y.OpinionType == 0;
23         break;
24     case OpinionType.中评:
25         expOpinionType = Y => Y.OpinionType == 1;
26         break;
27     case OpinionType.差评:
28         expOpinionType = Y => Y.OpinionType == 2;
29         break;
30 }
31 
32 switch (opinTime) {
33     case OpinionTime.一个星期内:
34         expOpinionTime = Y => (DateTime.Now - Y.OpinionTime).Days <= 7;
35         break;
36     case OpinionTime.一个月以内:
37         expOpinionTime = Y => (DateTime.Now - Y.OpinionTime).Days <= 30;
38         break;
39     case OpinionTime.六个月以内:
40         expOpinionTime = Y => (DateTime.Now - Y.OpinionTime).Days <= 180;
41         break;
42     case OpinionTime.六个月以外:
43         expOpinionTime = Y => (DateTime.Now - Y.OpinionTime).Days > 180;
44         break;
45 }
46 
47 //GetPaged(params) 这个方法是用来获取列表并支持缓存保存的.
48 return GetPaged(expSearchType.ContactExpressions<split_Opinion, bool>(expOpinionType, expOpinionTime),
49     userID.UserTablePrefx(), true, pageIndex, pageSize);

 

 

转载于:https://www.cnblogs.com/yans/archive/2009/01/05/1369006.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值