两三个月前曾写过《重构ConditionHelper》的随笔,但不知是因为写得不够好还是没有什么新意,我发表至博客园首页时被屏蔽了,本着好的知识应该分享给更多人,加之新项目已交付用户使用所以现在时间也还算充足,所以就打算重新写一下这篇文章。

  废话就不多说了,先上代码,然后就其中一些自己觉得写得还好的地方说一下自己的思路。

 #region  public enum Comparison
public enum Comparison
{
/// <summary>
/// 等于号 =
/// </summary>
Equal,
/// <summary>
/// 不等于号 <>
/// </summary>
NotEqual,
/// <summary>
/// 大于号 >
/// </summary>
GreaterThan,
/// <summary>
/// 大于或等于 >=
/// </summary>
GreaterOrEqual,
/// <summary>
/// 小于 <
/// </summary>
LessThan,
/// <summary>
/// 小于或等于 <=
/// </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 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 int Length
private int length=;
public int Length
{
get { return length; }
}
#endregion #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()
{
this.length = ;
parameterList.Clear();
conditionBuilder.Clear().Append(" Where ");
return this;
}
#endregion #region public ConditionHelper AppendCondition<T>(RelationType relationType, string fieldName, Comparison comparison, params T[] 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<T>(RelationType relationType, string fieldName, Comparison comparison, params T[] 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<T>(string fieldName, Comparison comparison, params T[] fieldValue)
/// <summary>
/// 添加条件
/// </summary>
/// <param name="comparison">比较符类型</param>
/// <param name="fieldName">字段名称</param>
/// <param name="fieldValue">字段值,注:1、不可为数组;2、Between时,此字段必须填两个值; </param>
/// <returns>返回ConditionHelper</returns>
public ConditionHelper AppendCondition<T>(string fieldName, Comparison comparison, params T[] 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), 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("条件未定义");
}
this.length++;
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);
}
this.length++;
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 #region 静态方法
/// <summary>
/// 取得condition中Sql条件语句:(包含Where关键字)
/// </summary>
/// <param name="condition"></param>
/// <returns>若condition为null时返回空字符串</returns>
public static string ToString(ConditionHelper condition)
{
if (condition != null)
return condition.ToString();
return string.Empty;
} /// <summary>
/// 取得condition中sql参数列表
/// </summary>
/// <param name="condition"></param>
/// <returns></returns>
public static List<SqlParameter> GetParamList(ConditionHelper condition)
{
if (condition == null || condition.ParameterList.Count < )
return null;
return condition.ParameterList;
}
#endregion #endregion #region 私有方法
/// <summary>
/// 取得字段值
/// </summary>
/// <param name="fieldValue"></param>
/// <returns></returns>
private string GetFieldValue<T>(params T[] fieldValue)
{
if (isBuildParameterSql == true)
{
List<string> parameterNameList = new List<string>();
foreach (var value in fieldValue)
{
parameterNameList.Add(AddParameter(value));
}
return string.Join(",", parameterNameList);
}
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<T>(params T[] 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 = " AND ";
break;
case RelationType.OR:
result = " 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 }

  变量isExcludeEmpty:是标识是否排除条件值为空的条件,这个在第一篇《ConditionHelper》里已经说过,在这里就不废话了。

  变量isBuildParameterSql:这是用来标识拼接的sql语句是否使用参数化。比如我们一般情况下为了防止SQL注入,我们都是使用参数化的查询语句,但毕竟使用参数化的语句没有直接使用普通的sql语句来的方便;另外这也是为了更好的兼容性,因为有时别的框架里就需要非参数化的条件语句。

  Clear方法:之前构想这个类时没有想到要写这个方法,但后来使用时却发现有必要添加。比如在同一个方法里要使用Condition两次的话,如果没有这个方法就则必需要声明两个ConditionHelper变量,另外我们写代码最不喜欢的就是复制粘贴,而现在只要在之前那变量上直接调用Clear方法是不是使用起来更爽呢。

  拼接条件的方法是由两个名为AppendCondition的重载方法和一个AppendParenthese方法组成。之前方法的命名是使用Add,但自己觉得这方法名总是感觉怪怪的,所以就改成了Append。AppendCondition之所以使用泛型方法,是因为我们在拼接条件时,其使用的值不一定总是字符串。

  public ConditionHelper AppendCondition<T>(RelationType relationType, string fieldName, Comparison comparison, params T[] 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;
}

上面代码第5行添加了一个条件判断,是为了防止使用该方法之前已经拼接了条件,但那些条件值为空而没有拼成语句,这样最后就会拼成where and name="张三"之类的语句。像一些刚学c#的人,可能在使用拼接SQL时先时直接在条件语句where后先加一名“1=1"再去拼接,这样虽然解决了问题,但是这样会造成sql查询时进行全表扫描,这样是很不好的一种解决方法。

 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;
}

AppendParenthese方法是在拼接需要使用括号括起来的条件时使用,虽然使用这个方法不够简洁,但是不用担心拼接出来的语句会出错。在之前那个版本的ConditionHelper中,拼接含括号的条件比这简洁,但有时写代码时不注意的话就会出现拼接出来的语句中会出现只有左括号而没有右括号的情况,有时又会出现有括号而括号里没有任何条件的语句,这是在使用时才发现的问题。

  其中两个静态方法ToString和GetParamList,是为了防止Condition为空时出错而添加的。

重构后的ConditionHelper的更多相关文章

  1. 重构前VS重构后效果对比

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42554641 学习重构已经一个多月了,虽然不能让代码特别的 ...

  2. mysql查看执行计划重构后的查询

    MYSQL优化器会对客服端发送的SQL语句进行优化,优化后的SQL语句再被MYSQL执行.然后我们在优化SQL的时候,怎么获取到MYSQL优化后执行语句呢. EXPLAIN select * from ...

  3. 使用Lazy对构造进行重构后比较

    用于测试在是否使用Lazy 的情况下,服务器负载,及服务提供情况对比.     服务器环境:   在此机器上安装了1 Hyper-V ,分配走1G内存,同时在本地上安装 SQLServer ,   在 ...

  4. 重构后的程序:通过rsync命令抓取日志文件

    push.sh #!/bin/bash function push() { local ip=$ local user=$ local password=$ local path=$ local lo ...

  5. 重构ConditionHelper

    在上一篇日志写了ConditionHelper的具体实现方法和它的用法,但那时只是把心里所想的一个思路用代码记录下来,而没有经过实践检 验的,难免存在一些问题,但在最近的一个新项目中用到Conditi ...

  6. ASP.NET MVC5+EF6+EasyUI 后台管理系统(58)-DAL层重构

    系列目录 前言:这是对本文系统一次重要的革新,很久就想要重构数据访问层了,数据访问层重复代码太多.主要集中增删该查每个模块都有,所以本次是为封装相同接口方法 如果你想了解怎么重构普通的接口DAL层请查 ...

  7. 产品前端重构(TypeScript、MVC框架设计)

    最近两周完成了对公司某一产品的前端重构,本文记录重构的主要思路及相关的设计内容. 公司期望把某一管理类信息系统从项目代码中抽取.重构为一个可复用的产品.该系统的前端是基于 ExtJs 5 进行构造的, ...

  8. 重构sql server的sys.sp_helptext存储

    本文目录列表: 1.sys.sp_helptext存储的功能和效果 2.重构sys.sp_helptext存储(命名为dbo.usp_helptext)提供直观的效果 3.sys.sp_helptex ...

  9. ReactiveCocoa代码实践之-RAC网络请求重构

    前言 RAC相比以往的开发模式主要有以下优点:提供了统一的消息传递机制:提供了多种奇妙且高效的信号操作方法:配合MVVM设计模式和RAC宏绑定减少多端依赖. RAC的理论知识非常深厚,包含有FRP,高 ...

随机推荐

  1. js正则验证手机号码有效性

    验证130-139,150-159,180-189号码段的手机号码 <script type="text/javascript"> [-]{})|([-]{})|([- ...

  2. BCM wifi驱动学习

    BCMwifi驱动学习 一.wifi详解1 1.代码路径:Z:\home\stonechen\svn\TD550_X\TD550\3rdparty\wifi\BCM43362\special\bcmd ...

  3. Swift - 多线程实现方式(1) - NSThread

    1,Swift继续使用Object-C原有的一套线程,包括三种多线程编程技术: (1)NSThread (2)Cocoa NSOperation(NSOperation和NSOperationQueu ...

  4. POJ 1955 Rubik's Cube

    暴力模拟就好了.... vim写代码真费事,手都写酸了... Rubik's Cube Time Limit: 1000MS   Memory Limit: 30000K Total Submissi ...

  5. boost:asio编译

    参考:http://hi.baidu.com/need_for_dream/blog/item/c14a28086a504c33e92488b5.html 环境: VS2010, boost1.38. ...

  6. hdu 4550 贪婪 思考题 权

    http://acm.hdu.edu.cn/showproblem.php?pid=4550 想了挺久,然后各种分类 最终AC,假设是现场,对自己没信心的话,预计还是要WA,,,,,,然后搜题解,发现 ...

  7. SVN权限解析规则详解(转)

    首先创建一个版本库后,会生成最初的目录结构和基本的配置文件,本文主要分析“authz”文件的内容:我们先抛开alias和groups不谈,将重点放在路径的权限配置上. 一. 权限格式 svn权限的基本 ...

  8. Java使用javax.mail.jar发送邮件并同意发送附件

    因为Java在开发网页上占有绝大优势.所以作为web端的领军人物,譬如发送短信和发送邮件这些就成了必定,网络安全一再安全我们须要把账号的安全级别提到更高.因此这些对于开发者也就成了必须掌握的技能!我一 ...

  9. MySQL如何修改root密码

    MySQL修改用户密码         因为长期不登录MySQL数据库,登录时经常忘记root权限密码.本文提供一个在数据库服务器上修改root密码的方法,本文撰写基础是在xp操作系统下进行. 第一步 ...

  10. 14.4.3.5 Configuring InnoDB Buffer Pool Flushing 配置InnoDB Buffer Pool 刷新:

    14.4.3.5 Configuring InnoDB Buffer Pool Flushing 配置InnoDB Buffer Pool 刷新: InnoDB执行某些任务在后台, 包括flush 脏 ...