重构ConditionHelper

  在上一篇日志写了ConditionHelper的具体实现方法和它的用法,但那时只是把心里所想的一个思路用代码记录下来,而没有经过实践检 验的,难免存在一些问题,但在最近的一个新项目中用到ConditionHelper时,才发现其中问题不少,最简单的问题是方法名取得有问题,如 AddAndCondition、AddOrCondition等,不注意的话很容易弄错,所以在重构的过程把这些方法合并成了一个方法,另外还有在使用 时如遇到一些特殊情况还会出错,在重构后把这些问题都修复了,至少用了一两个星期了没有发现新的Bug,但也不能保证不存在Bug了,只能说应该基本是没 什么问题了。

  在使用ConditionHelper的过程中,自己觉得比以前用的方法方便很多了,写出来的代码也精简了不少,看着都舒服些。

   以前本来想着改进后直接把上一篇日志修改一下就行了,但自己觉得重构后的代码与重构前的代码有很大的区别,所以想着也没必要把以前不好的东西直接一笔抹 杀,这样也方便以后看看其中的区别。自己最近在重新写框架时,看着以前写的框架有很多地方是写得很啰嗦的,但自己当时并没有这么觉得,有时代码隔一段时间 回头来看你就会发现原来还可以这样精简一下,这并不一定是水平提高的原因,人有时一心放在一件事情上反而不能把事情做好,偶尔把自己的视线移到别的地方, 再回头来看,也许你会发觉原来还可以这样子写。

  好了,废话不多说了,以下是重构后的全部代码:      

1     #region  public enum Comparison
  2     public enum Comparison
  3     {
  4         /// <summary>
  5         /// 等于号 =
  6         /// </summary>
  7         Equal,
  8         /// <summary>
  9         /// 不等于号 <>
 10         /// </summary>
 11         NotEqual,
 12         /// <summary>
 13         /// 大于号 >
 14         /// </summary>
 15         GreaterThan,
 16         /// <summary>
 17         /// 大于或等于 >=
 18         /// </summary>
 19         GreaterOrEqual,
 20         /// <summary>
 21         /// 小于 <
 22         /// </summary>
 23         LessThan,
 24         /// <summary>
 25         /// 小于或等于 <=
 26         /// </summary>
 27         LessOrEqual,
 28         /// <summary>
 29         /// 模糊查询 Like
 30         /// </summary>
 31         Like,
 32         /// <summary>
 33         /// 模糊查询  Not Like
 34         /// </summary>
 35         NotLike,
 36         /// <summary>
 37         /// is null
 38         /// </summary>
 39         IsNull,
 40         /// <summary>
 41         /// is not null
 42         /// </summary>
 43         IsNotNull,
 44         /// <summary>
 45         /// in
 46         /// </summary>
 47         In,
 48         /// <summary>
 49         /// not in
 50         /// </summary>
 51         NotIn,
 52         /// <summary>
 53         /// 左括号 (
 54         /// </summary>
 55         OpenParenthese,
 56         /// <summary>
 57         /// 右括号 )
 58         /// </summary>
 59         CloseParenthese,
 60         Between,
 61         StartsWith,
 62         EndsWith
 63     }
 64     #endregion
 65 
 66     #region public enum RelationType
 67     /// <summary>
 68     /// 关联类型:And、Or
 69     /// </summary>
 70     public enum RelationType
 71     {
 72         AND,
 73         OR,
 74     }
 75     #endregion
 76 
 77 
 78     /// <summary>
 79     /// 文件名:ConditionHelper
 80     /// 功能描述:条件帮助类
 81     /// </summary>
 82     public class ConditionHelper
 83     {
 84         #region 变量、属性定义
 85         string parameterPrefix = "@";
 86         string parameterKey = "P";
 87         /// <summary>
 88         /// 用来拼接SQL语句
 89         /// </summary>
 90         StringBuilder conditionBuilder = new StringBuilder();
 91         /// <summary>
 92         /// 为True时表示字段为空或者Null时则不作为查询条件
 93         /// </summary>
 94         bool isExcludeEmpty = true;
 95         /// <summary>
 96         /// 是否生成带参数的sql
 97         /// </summary>
 98         bool isBuildParameterSql = true;
 99 
100         #region public List<SqlParameter> ParameterList
101         private List<SqlParameter> parameterList = new List<SqlParameter>();
102         /// <summary>
103         /// 参数列表
104         /// </summary>
105         public List<SqlParameter> ParameterList
106         {
107             get { return this.parameterList; }
108         } 
109         #endregion
110 
111         int index = 0;
112 
113         #endregion
114 
115         #region 构造函数
116         /// <summary>
117         /// 创建ConditionHelper对象
118         /// </summary>
119         /// <param name="isExcludeEmpty">为True时表示字段为空或者Null时则不作为查询条件</param>
120         /// <param name="isBuildParameterSql">是否生成带参数的sql</param>
121         /// <param name="parameterKey">参数的前辍</param>
122         public ConditionHelper(bool isExcludeEmpty = true, string parameterKey = "P", bool isBuildParameterSql = true)
123         {
124             this.isExcludeEmpty = isExcludeEmpty;
125             this.isBuildParameterSql = isBuildParameterSql;
126             this.parameterKey = parameterKey;
127             this.conditionBuilder.Append(" Where ");
128         }
129         #endregion
130 
131         #region 公共方法
132         #region  public ConditionHelper Clear()  清除已添加的条件
133         /// <summary>
134         /// 清除已添加的条件
135         /// </summary> 
136         /// <returns></returns>
137         public ConditionHelper Clear()
138         {
139             parameterList.Clear();
140             conditionBuilder.Clear().Append(" Where ");
141             return this;
142         }
143         #endregion
144 
145         #region public ConditionHelper AppendCondition(RelationType relationType, string fieldName, Comparison comparison, params object[] fieldValue) 添加条件
146         /// <summary>
147         /// 添加条件
148         /// </summary>
149         /// <param name="relationType">关联运算符</param>
150         /// <param name="comparison">比较符类型</param>
151         /// <param name="fieldName">字段名称</param>
152         /// <param name="fieldValue">字段值,注:1、不可为数组;2、Between时,此字段必须填两个值; </param>
153         /// <returns>返回ConditionHelper</returns>
154         public ConditionHelper AppendCondition(RelationType relationType, string fieldName, Comparison comparison, params object[] fieldValue)
155         {
156             if (IsContinue(fieldValue)) return this;
157 
158             if (!this.conditionBuilder.ToString().Trim().EndsWith("WHERE", StringComparison.InvariantCultureIgnoreCase))
159             {
160                 this.conditionBuilder.Append(GetRelationString(relationType));
161             }
162             this.AppendCondition(fieldName, comparison, fieldValue);
163             return this;
164         }
165         #endregion
166 
167         #region public ConditionHelper AppendCondition(string fieldName, Comparison comparison, params object[] fieldValue)
168         /// <summary>
169         /// 添加条件
170         /// </summary>
171         /// <param name="comparison">比较符类型</param>
172         /// <param name="fieldName">字段名称</param>
173         /// <param name="fieldValue">字段值,注:1、不可为数组;2、Between时,此字段必须填两个值; </param>
174         /// <returns>返回ConditionHelper</returns>
175         public ConditionHelper AppendCondition(string fieldName, Comparison comparison, params object[] fieldValue)
176         {
177             if (IsContinue(fieldValue)) return this;
178 
179             switch (comparison)
180             {
181                 case Comparison.Equal:
182                 case Comparison.NotEqual:
183                 case Comparison.GreaterThan:
184                 case Comparison.GreaterOrEqual:
185                 case Comparison.LessThan:
186                 case Comparison.LessOrEqual:
187                     this.conditionBuilder.AppendFormat("{0}{1}{2}", GetFieldName(fieldName), GetComparisonOperator(comparison), GetFieldValue(fieldValue[0]));
188                     break;
189                 case Comparison.IsNull:
190                 case Comparison.IsNotNull:
191                     this.conditionBuilder.AppendFormat("{0}{1}", GetFieldName(fieldName), GetComparisonOperator(comparison));
192                     break;
193                 case Comparison.Like:
194                 case Comparison.NotLike:
195                     this.conditionBuilder.AppendFormat("{0}{1}{2}", GetFieldName(fieldName), GetComparisonOperator(comparison), GetFieldValue(string.Format("%{0}%", fieldValue[0])));
196                     break;
197                 case Comparison.In:
198                 case Comparison.NotIn:
199                     this.conditionBuilder.AppendFormat("{0}{1}({2})", GetFieldName(fieldName), GetComparisonOperator(comparison), string.Join(",", GetFieldValue(fieldValue)));
200                     break;
201                 case Comparison.StartsWith:
202                     this.conditionBuilder.AppendFormat("{0}{1}{2}", GetFieldName(fieldName), GetComparisonOperator(comparison), GetFieldValue(string.Format("{0}%", fieldValue[0])));
203                     break;
204                 case Comparison.EndsWith:
205                     this.conditionBuilder.AppendFormat("{0}{1}{2}", GetFieldName(fieldName), GetComparisonOperator(comparison), GetFieldValue(string.Format("%{0}", fieldValue[0])));
206                     break;
207                 case Comparison.Between:
208                     this.conditionBuilder.AppendFormat("{0}{1}{2} AND {3}", GetFieldName(fieldName), GetComparisonOperator(comparison), GetFieldValue(fieldValue[0]), GetFieldValue(fieldValue[1]));
209                     break;
210                 default:
211                     throw new Exception("条件为定义");
212             }
213             return this;
214         }
215         #endregion
216 
217         #region public ConditionHelper AppendParenthese(RelationType relationType, ConditionHelper condition)
218         /// <summary>
219         /// 添加含有括号的条件
220         /// </summary>
221         /// <param name="relationType">关联运算符</param>
222         /// <param name="condition">条件</param>
223         /// <returns></returns>
224         public ConditionHelper AppendParenthese(RelationType relationType, ConditionHelper condition)
225         {
226             if (condition == null || condition.conditionBuilder.ToString().Trim().Length < 6)
227                 return this;
228             if (!conditionBuilder.ToString().Trim().EndsWith("WHERE", StringComparison.InvariantCultureIgnoreCase))
229             {
230                 this.conditionBuilder.Append(GetRelationString(relationType));
231             }
232             this.conditionBuilder.AppendFormat(" ({0}) ", condition.conditionBuilder.ToString().Remove(0, 6));
233             if (condition.parameterList.Count > 0)
234             {
235                 this.parameterList.AddRange(condition.parameterList);
236             }
237             return this;
238         }
239         #endregion
240 
241         #region public override string ToString()
242         /// <summary>
243         /// 转化成Sql条件语句:(包含Where关键字)
244         /// </summary>
245         /// <returns></returns>
246         public override string ToString()
247         {
248             if (this.conditionBuilder.Length < 8)
249                 return string.Empty;
250             return this.conditionBuilder.ToString();
251         }
252         #endregion
253 
254         #endregion
255 
256 
257         #region 私有方法
258         /// <summary>
259         /// 取得字段值
260         /// </summary>
261         /// <param name="fieldValue"></param>
262         /// <returns></returns>
263         private string GetFieldValue(params object[] fieldValue)
264         {
265             if (isBuildParameterSql == true)
266             {
267                 if (fieldValue.Length < 2)
268                 {
269                     return AddParameter(fieldValue[0]);
270                 }
271                 else
272                 {
273                     List<string> parameterNameList = new List<string>();
274                     foreach (var value in fieldValue)
275                     {
276                         parameterNameList.Add(AddParameter(value));
277                     }
278                     return string.Join(",", parameterNameList);
279                 }
280             }
281             else
282             {
283                 if (fieldValue.Length < 2)
284                 {
285                     return string.Format("'{0}'", fieldValue[0]);
286                 }
287                 else
288                 {
289                     return string.Format("'{0}'", string.Join("','", fieldValue));
290                 }
291             }
292         }
293 
294         /// <summary>
295         /// 添加参数
296         /// </summary>
297         /// <param name="fieldValue"></param>
298         /// <returns></returns>
299         private string AddParameter(object fieldValue)
300         {
301             index++;
302             string parameterName = string.Format("{0}{1}{2}", parameterPrefix, parameterKey, index);
303             this.parameterList.Add(new SqlParameter
304              {
305                  ParameterName = parameterName,
306                  Value = fieldValue ?? DBNull.Value
307              });
308             return parameterName;
309         }
310 
311         private string GetFieldName(string fieldName)
312         {
313             return string.Format("{0}", fieldName);
314         }
315 
316         /// <summary>
317         /// 用来判断是否跳过此拼接条件
318         /// </summary>
319         /// <param name="fieldValue">字段值</param>
320         /// <returns>返回True表示跳过,否则不跳过</returns>
321         private bool IsContinue(params object[] fieldValue)
322         {
323             bool result = false;
324             //如果选择IsExcludeEmpty为True,并且该字段为空值的话则跳过
325             if (isExcludeEmpty && fieldValue != null && fieldValue.Length > 0 && string.IsNullOrEmpty(fieldValue[0] + ""))
326                 result = true;
327             return result;
328         }
329 
330         /// <summary>
331         /// 取得关联类型字符串
332         /// </summary>
333         /// <param name="relationType"></param>
334         /// <returns></returns>
335         private static string GetRelationString(RelationType relationType)
336         {
337             string result = string.Empty;
338             switch (relationType)
339             {
340                 case RelationType.AND:
341                     result = SqlKeyWords.AND;
342                     break;
343                 case RelationType.OR:
344                     result = SqlKeyWords.OR;
345                     break;
346             }
347             return result;
348         }
349 
350         /// <summary>
351         /// 取得关系运算符
352         /// </summary>
353         /// <param name="comparison"></param>
354         /// <returns></returns>
355         private static string GetComparisonOperator(Comparison comparison)
356         {
357             string result = string.Empty;
358             switch (comparison)
359             {
360                 case Comparison.Equal:
361                     result = " = ";
362                     break;
363                 case Comparison.NotEqual:
364                     result = " <> ";
365                     break;
366                 case Comparison.GreaterThan:
367                     result = " > ";
368                     break;
369                 case Comparison.GreaterOrEqual:
370                     result = " >= ";
371                     break;
372                 case Comparison.LessThan:
373                     result = " < ";
374                     break;
375                 case Comparison.LessOrEqual:
376                     result = " <= ";
377                     break;
378                 case Comparison.Like:
379                 case Comparison.StartsWith:
380                 case Comparison.EndsWith:
381                     result = " LIKE ";
382                     break;
383                 case Comparison.NotLike:
384                     result = " NOT LIKE ";
385                     break;
386                 case Comparison.IsNull:
387                     result = " IS NULL ";
388                     break;
389                 case Comparison.IsNotNull:
390                     result = " IS NOT NULL ";
391                     break;
392                 case Comparison.In:
393                     result = " IN ";
394                     break;
395                 case Comparison.NotIn:
396                     result = " NOT IN ";
397                     break;
398                 case Comparison.OpenParenthese:
399                     result = " (";
400                     break;
401                 case Comparison.CloseParenthese:
402                     result = ") ";
403                     break;
404                 case Comparison.Between:
405                     result = " BETWEEN ";
406                     break;
407                 default:
408                     throw new Exception("条件未定义!");
409             }
410             return result;
411         }
412         #endregion
413 
414     }
View Code

   重构后添加条件的方法就只有AppendCondition和AppendCondition的重载以及AppendParenthese三个方法,方法名字把Add改为Append,总觉得Add做为方法名有点怪怪的,AppendParenthese为添加含有括号的条件,在上一篇日志中的ConditionHelper中关于括号的条件组合是存在问题的,有时存在添加了左括号而没有右括号的情况,在重构号把左右括号放在一个方法里就不存在这个问题了。另外根据自己项目的需要,添加了Clear方法,以便清除先前添加进去的条件。

  以下是我在一个项目中用到ConditionHelper的一个例子:

  

 1         /// <summary>
 2         /// 通过登录账号和密码查找用户
 3         /// </summary>
 4         /// <param name="userID">登录账号</param>
 5         /// <param name="password">加密前的密码</param>
 6         /// <returns>返回用户信息</returns>
 7         public SysUserInfo FindByUser(string userID, string password)
 8         {
 9             if (string.IsNullOrEmpty(userID))
10                 return null;
11             password = Encrypt(password);
12             ConditionHelper condition = new ConditionHelper();
13             condition.AppendCondition(SysUserInfo.F_UserID, Comparison.Equal, userID)
14                      .AppendCondition(RelationType.AND, SysUserInfo.F_Password, Comparison.Equal, password);
15             return this.Find(condition);
16         }
View Code

 

posted @ 2015-08-09 22:29  Eric-Lau  阅读(488)  评论(0编辑  收藏  举报