重构ConditionHelper
在上一篇日志写了ConditionHelper的具体实现方法和它的用法,但那时只是把心里所想的一个思路用代码记录下来,而没有经过实践检 验的,难免存在一些问题,但在最近的一个新项目中用到ConditionHelper时,才发现其中问题不少,最简单的问题是方法名取得有问题,如 AddAndCondition、AddOrCondition等,不注意的话很容易弄错,所以在重构的过程把这些方法合并成了一个方法,另外还有在使用 时如遇到一些特殊情况还会出错,在重构后把这些问题都修复了,至少用了一两个星期了没有发现新的Bug,但也不能保证不存在Bug了,只能说应该基本是没 什么问题了。
在使用ConditionHelper的过程中,自己觉得比以前用的方法方便很多了,写出来的代码也精简了不少,看着都舒服些。
以前本来想着改进后直接把上一篇日志修改一下就行了,但自己觉得重构后的代码与重构前的代码有很大的区别,所以想着也没必要把以前不好的东西直接一笔抹 杀,这样也方便以后看看其中的区别。自己最近在重新写框架时,看着以前写的框架有很多地方是写得很啰嗦的,但自己当时并没有这么觉得,有时代码隔一段时间 回头来看你就会发现原来还可以这样精简一下,这并不一定是水平提高的原因,人有时一心放在一件事情上反而不能把事情做好,偶尔把自己的视线移到别的地方, 再回头来看,也许你会发觉原来还可以这样子写。
好了,废话不多说了,以下是重构后的全部代码:
#region public enum Comparison
public enum Comparison
{
/// <summary>
/// 等于号 =
/// </summary>
Equal,
/// <summary>
/// 不等于号 <>
/// </summary>
NotEqual,
/// <summary>
/// 大于号 >
/// </summary>
GreaterThan,
/// <summary>
/// 大于或等于 >=
/// </summary>
GreaterOrEqual,
/// <summary>
/// 小于 <
22 /// </summary>
LessThan,
/// <summary>
/// 小于或等于 <=
26 /// </summary>
LessOrEqual,
/// <summary>
/// 模糊查询 Like
/// </summary>
Like,
/// <summary>
/// 模糊查询 Not Like
/// </summary>
NotLike,
/// <summary>
/// is null
/// </summary>
IsNull,
/// <summary>
/// is not null
/// </summary>
IsNotNull,
/// <summary>
/// in
/// </summary>
In,
/// <summary>
/// not in
/// </summary>
NotIn,
/// <summary>
/// 左括号 (
/// </summary>
OpenParenthese,
/// <summary>
/// 右括号 )
/// </summary>
CloseParenthese,
Between,
StartsWith,
EndsWith
}
#endregion #region public enum RelationType
/// <summary>
/// 关联类型:And、Or
/// </summary>
public enum RelationType
{
AND,
OR,
}
#endregion /// <summary>
/// 文件名:ConditionHelper
/// 功能描述:条件帮助类
/// </summary>
public class ConditionHelper
{
#region 变量、属性定义
string parameterPrefix = "@";
string parameterKey = "P";
/// <summary>
/// 用来拼接SQL语句
/// </summary>
StringBuilder conditionBuilder = new StringBuilder();
/// <summary>
/// 为True时表示字段为空或者Null时则不作为查询条件
/// </summary>
bool isExcludeEmpty = true;
/// <summary>
/// 是否生成带参数的sql
/// </summary>
bool isBuildParameterSql = true; #region public List<SqlParameter> ParameterList
private List<SqlParameter> parameterList = new List<SqlParameter>();
/// <summary>
/// 参数列表
/// </summary>
public List<SqlParameter> ParameterList
{
get { return this.parameterList; }
}
#endregion int index = ; #endregion #region 构造函数
/// <summary>
/// 创建ConditionHelper对象
/// </summary>
/// <param name="isExcludeEmpty">为True时表示字段为空或者Null时则不作为查询条件</param>
/// <param name="isBuildParameterSql">是否生成带参数的sql</param>
/// <param name="parameterKey">参数的前辍</param>
public ConditionHelper(bool isExcludeEmpty = true, string parameterKey = "P", bool isBuildParameterSql = true)
{
this.isExcludeEmpty = isExcludeEmpty;
this.isBuildParameterSql = isBuildParameterSql;
this.parameterKey = parameterKey;
this.conditionBuilder.Append(" Where ");
}
#endregion #region 公共方法
#region public ConditionHelper Clear() 清除已添加的条件
/// <summary>
/// 清除已添加的条件
/// </summary>
/// <returns></returns>
public ConditionHelper Clear()
{
parameterList.Clear();
conditionBuilder.Clear().Append(" Where ");
return this;
}
#endregion #region public ConditionHelper AppendCondition(RelationType relationType, string fieldName, Comparison comparison, params object[] fieldValue) 添加条件
/// <summary>
/// 添加条件
/// </summary>
/// <param name="relationType">关联运算符</param>
/// <param name="comparison">比较符类型</param>
/// <param name="fieldName">字段名称</param>
/// <param name="fieldValue">字段值,注:1、不可为数组;2、Between时,此字段必须填两个值; </param>
/// <returns>返回ConditionHelper</returns>
public ConditionHelper AppendCondition(RelationType relationType, string fieldName, Comparison comparison, params object[] fieldValue)
{
if (IsContinue(fieldValue)) return this; if (!this.conditionBuilder.ToString().Trim().EndsWith("WHERE", StringComparison.InvariantCultureIgnoreCase))
{
this.conditionBuilder.Append(GetRelationString(relationType));
}
this.AppendCondition(fieldName, comparison, fieldValue);
return this;
}
#endregion #region public ConditionHelper AppendCondition(string fieldName, Comparison comparison, params object[] fieldValue)
/// <summary>
/// 添加条件
/// </summary>
/// <param name="comparison">比较符类型</param>
/// <param name="fieldName">字段名称</param>
/// <param name="fieldValue">字段值,注:1、不可为数组;2、Between时,此字段必须填两个值; </param>
/// <returns>返回ConditionHelper</returns>
public ConditionHelper AppendCondition(string fieldName, Comparison comparison, params object[] fieldValue)
{
if (IsContinue(fieldValue)) return this; switch (comparison)
{
case Comparison.Equal:
case Comparison.NotEqual:
case Comparison.GreaterThan:
case Comparison.GreaterOrEqual:
case Comparison.LessThan:
case Comparison.LessOrEqual:
this.conditionBuilder.AppendFormat("{0}{1}{2}", GetFieldName(fieldName), GetComparisonOperator(comparison), GetFieldValue(fieldValue[]));
break;
case Comparison.IsNull:
case Comparison.IsNotNull:
this.conditionBuilder.AppendFormat("{0}{1}", GetFieldName(fieldName), GetComparisonOperator(comparison));
break;
case Comparison.Like:
case Comparison.NotLike:
this.conditionBuilder.AppendFormat("{0}{1}{2}", GetFieldName(fieldName), GetComparisonOperator(comparison), GetFieldValue(string.Format("%{0}%", fieldValue[])));
break;
case Comparison.In:
case Comparison.NotIn:
this.conditionBuilder.AppendFormat("{0}{1}({2})", GetFieldName(fieldName), GetComparisonOperator(comparison), string.Join(",", GetFieldValue(fieldValue)));
break;
case Comparison.StartsWith:
this.conditionBuilder.AppendFormat("{0}{1}{2}", GetFieldName(fieldName), GetComparisonOperator(comparison), GetFieldValue(string.Format("{0}%", fieldValue[])));
break;
case Comparison.EndsWith:
this.conditionBuilder.AppendFormat("{0}{1}{2}", GetFieldName(fieldName), GetComparisonOperator(comparison), GetFieldValue(string.Format("%{0}", fieldValue[])));
break;
case Comparison.Between:
this.conditionBuilder.AppendFormat("{0}{1}{2} AND {3}", GetFieldName(fieldName), GetComparisonOperator(comparison), GetFieldValue(fieldValue[]), GetFieldValue(fieldValue[]));
break;
default:
throw new Exception("条件为定义");
}
return this;
}
#endregion #region public ConditionHelper AppendParenthese(RelationType relationType, ConditionHelper condition)
/// <summary>
/// 添加含有括号的条件
/// </summary>
/// <param name="relationType">关联运算符</param>
/// <param name="condition">条件</param>
/// <returns></returns>
public ConditionHelper AppendParenthese(RelationType relationType, ConditionHelper condition)
{
if (condition == null || condition.conditionBuilder.ToString().Trim().Length < )
return this;
if (!conditionBuilder.ToString().Trim().EndsWith("WHERE", StringComparison.InvariantCultureIgnoreCase))
{
this.conditionBuilder.Append(GetRelationString(relationType));
}
this.conditionBuilder.AppendFormat(" ({0}) ", condition.conditionBuilder.ToString().Remove(, ));
if (condition.parameterList.Count > )
{
this.parameterList.AddRange(condition.parameterList);
}
return this;
}
#endregion #region public override string ToString()
/// <summary>
/// 转化成Sql条件语句:(包含Where关键字)
/// </summary>
/// <returns></returns>
public override string ToString()
{
if (this.conditionBuilder.Length < )
return string.Empty;
return this.conditionBuilder.ToString();
}
#endregion #endregion #region 私有方法
/// <summary>
/// 取得字段值
/// </summary>
/// <param name="fieldValue"></param>
/// <returns></returns>
private string GetFieldValue(params object[] fieldValue)
{
if (isBuildParameterSql == true)
{
if (fieldValue.Length < )
{
return AddParameter(fieldValue[]);
}
else
{
List<string> parameterNameList = new List<string>();
foreach (var value in fieldValue)
{
parameterNameList.Add(AddParameter(value));
}
return string.Join(",", parameterNameList);
}
}
else
{
if (fieldValue.Length < )
{
return string.Format("'{0}'", fieldValue[]);
}
else
{
return string.Format("'{0}'", string.Join("','", fieldValue));
}
}
} /// <summary>
/// 添加参数
/// </summary>
/// <param name="fieldValue"></param>
/// <returns></returns>
private string AddParameter(object fieldValue)
{
index++;
string parameterName = string.Format("{0}{1}{2}", parameterPrefix, parameterKey, index);
this.parameterList.Add(new SqlParameter
{
ParameterName = parameterName,
Value = fieldValue ?? DBNull.Value
});
return parameterName;
} private string GetFieldName(string fieldName)
{
return string.Format("{0}", fieldName);
} /// <summary>
/// 用来判断是否跳过此拼接条件
/// </summary>
/// <param name="fieldValue">字段值</param>
/// <returns>返回True表示跳过,否则不跳过</returns>
private bool IsContinue(params object[] fieldValue)
{
bool result = false;
//如果选择IsExcludeEmpty为True,并且该字段为空值的话则跳过
if (isExcludeEmpty && fieldValue != null && fieldValue.Length > && string.IsNullOrEmpty(fieldValue[] + ""))
result = true;
return result;
} /// <summary>
/// 取得关联类型字符串
/// </summary>
/// <param name="relationType"></param>
/// <returns></returns>
private static string GetRelationString(RelationType relationType)
{
string result = string.Empty;
switch (relationType)
{
case RelationType.AND:
result = SqlKeyWords.AND;
break;
case RelationType.OR:
result = SqlKeyWords.OR;
break;
}
return result;
} /// <summary>
/// 取得关系运算符
/// </summary>
/// <param name="comparison"></param>
/// <returns></returns>
private static string GetComparisonOperator(Comparison comparison)
{
string result = string.Empty;
switch (comparison)
{
case Comparison.Equal:
result = " = ";
break;
case Comparison.NotEqual:
result = " <> ";
break;
case Comparison.GreaterThan:
result = " > ";
break;
case Comparison.GreaterOrEqual:
result = " >= ";
break;
case Comparison.LessThan:
result = " < ";
break;
case Comparison.LessOrEqual:
result = " <= ";
break;
case Comparison.Like:
case Comparison.StartsWith:
case Comparison.EndsWith:
result = " LIKE ";
break;
case Comparison.NotLike:
result = " NOT LIKE ";
break;
case Comparison.IsNull:
result = " IS NULL ";
break;
case Comparison.IsNotNull:
result = " IS NOT NULL ";
break;
case Comparison.In:
result = " IN ";
break;
case Comparison.NotIn:
result = " NOT IN ";
break;
case Comparison.OpenParenthese:
result = " (";
break;
case Comparison.CloseParenthese:
result = ") ";
break;
case Comparison.Between:
result = " BETWEEN ";
break;
default:
throw new Exception("条件未定义!");
}
return result;
}
#endregion }
重构后添加条件的方法就只有AppendCondition和AppendCondition的重载以及AppendParenthese三个方法,方法名字把Add改为Append,总觉得Add做为方法名有点怪怪的,AppendParenthese为添加含有括号的条件,在上一篇日志中的ConditionHelper中关于括号的条件组合是存在问题的,有时存在添加了左括号而没有右括号的情况,在重构号把左右括号放在一个方法里就不存在这个问题了。另外根据自己项目的需要,添加了Clear方法,以便清除先前添加进去的条件。
以下是我在一个项目中用到ConditionHelper的一个例子:
/// <summary>
/// 通过登录账号和密码查找用户
/// </summary>
/// <param name="userID">登录账号</param>
/// <param name="password">加密前的密码</param>
/// <returns>返回用户信息</returns>
public SysUserInfo FindByUser(string userID, string password)
{
if (string.IsNullOrEmpty(userID))
return null;
password = Encrypt(password);
ConditionHelper condition = new ConditionHelper();
condition.AppendCondition(SysUserInfo.F_UserID, Comparison.Equal, userID)
.AppendCondition(RelationType.AND, SysUserInfo.F_Password, Comparison.Equal, password);
return this.Find(condition);
}
重构ConditionHelper的更多相关文章
- 重构后的ConditionHelper
两三个月前曾写过<重构ConditionHelper>的随笔,但不知是因为写得不够好还是没有什么新意,我发表至博客园首页时被屏蔽了,本着好的知识应该分享给更多人,加之新项目已交付用户使用所 ...
- 记一次.NET代码重构
好久没写代码了,终于好不容易接到了开发任务,一看时间还挺充足的,我就慢慢整吧,若是遇上赶进度,基本上直接是功能优先,完全不考虑设计.你可以认为我完全没有追求,当身后有鞭子使劲赶的时候,神马设计都是浮云 ...
- CSharpGL(17)重构CSharpGL
CSharpGL(17)重构CSharpGL CSharpGL用起来我自己都觉得繁琐了,这是到了重构的时候. 下载 CSharpGL已在GitHub开源,欢迎对OpenGL有兴趣的同学加入(https ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(58)-DAL层重构
系列目录 前言:这是对本文系统一次重要的革新,很久就想要重构数据访问层了,数据访问层重复代码太多.主要集中增删该查每个模块都有,所以本次是为封装相同接口方法 如果你想了解怎么重构普通的接口DAL层请查 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(59)-BLL层重构
系列目录 前言: 这应该是本系统最后一次重构,将重构BLL层和Model层.来完全取代代码生成器生成的BLL层和DAL层.完全废掉了代码生成器的DAL,BLL,MODEL层. 全自动生成增,删,改 ...
- 原生JS实现全屏切换以及导航栏滑动隐藏及显示——重构前
思路分析: 向后滚动鼠标滚轮,页面向下全屏切换:向前滚动滚轮,页面向上全屏切换.切换过程为动画效果. 第一屏时,导航栏固定在页面顶部,切换到第二屏时,导航条向左滑动隐藏.切换回第一屏时,导航栏向右滑动 ...
- Android重构与设计之路,从整理提示弹窗(SmartAlertPop)开始
封装一个独立弹窗Module,这里的弹窗包括普通的Dialog方式弹框和WindowManager方式弹窗.提供一种管理项目里面弹窗的方案,便于后期修改和维护. 首先描述一个在大项目中普遍存在的一个现 ...
- 产品前端重构(TypeScript、MVC框架设计)
最近两周完成了对公司某一产品的前端重构,本文记录重构的主要思路及相关的设计内容. 公司期望把某一管理类信息系统从项目代码中抽取.重构为一个可复用的产品.该系统的前端是基于 ExtJs 5 进行构造的, ...
- 一枚招聘信息——分期乐招页面重构/UI开发(8k-12k 深圳 经验1-3年 学历不限 全职)
腾讯人创建的分期乐公司,急需页面重构人才若干枚,公司前景好,机会难得,有兴趣的速速 8k-12k 深圳 经验1-3年 学历不限 全职 公司网站: http://www.fenqile.com/ 职位诱 ...
随机推荐
- EL表达式(2)
本篇介绍EL表达式的隐式对象,如同JSP一样,EL也封装了11个隐式对象,通过这些隐式对象可以在EL表达式中直接使用. 在使用EL时,其实EL是先看标识符是否是其隐式对象之一,如果不是,才从四个域(p ...
- 基于visual Studio2013解决面试题之0402合并升序链表并去重
题目
- input在苹果浏览器下变成圆角的解决方案
复制代码代码如下: .form-actions input{ ... -webkit-appearance: none; } 更新到iPhone一看,真爽,问题解决了.
- alv行可编辑时带出描述
ALV显示可以编辑的状态下可以带出描述信息等,比如维护表程序输入公司代码时需要带出公司代码的描述,这时就需要通过下面事件来触发 定义一个类: CLASS lcl_event_receiver DEFI ...
- Android菜鸟的成长笔记(6)——剖析源码学自定义主题Theme
原文:Android菜鸟的成长笔记(6)--剖析源码学自定义主题Theme 还记得在Android菜鸟的成长笔记(3)中我们曾经遇到了一个问题吗?"这个界面和真真的QQ界面还有点不同的就是上 ...
- 设定十分钟android在状态栏上集成的开源project推荐
1.前言 于android kitkat 有一个新功能可以设置背景的手机状态栏,让手机风的整个界面格是一致的,它看起来非常酷,在今年的google i/o向上android l这样的风格.来如今看我们 ...
- Swift - 解析JSON数据(内置NSJSONSerialization与第三方JSONKit)
一,使用自带的NSJSONSerialization 苹果从IOS5.0后推出了SDK自带的JSON解决方案NSJSONSerialization,这是一个非常好用的JSON生成和解析工具,效率也比其 ...
- 用Ajax删除的做法
一般程序文件代码 using System;using System.Web;using System.Linq;using System.Data.Linq; public class Shanch ...
- Python天天美味(25) - 深入理解yield
Python天天美味(25) - 深入理解yield - CoderZh - 博客园 Python天天美味(25) - 深入理解yield yield的英文单词意思是生产,刚接触Python的时候 ...
- Automatic logon configuration on Linux OS
Automatic logon configuration on Linux OS 1. Regarding to DSA: a) ssh-keygen -t dsa b) cat ~/.ssh/i ...