重构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 }
重构后添加条件的方法就只有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 }