两三个月前曾写过《重构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. Qt中使用OpenCV库

    原地址:http://blog.sina.com.cn/s/blog_5c70dfc80100qwi3.html 心情真是好啊,曾经一度想放弃使用Qt加OpenCV进行数字图像处理了,幸好坚持住了,今 ...

  2. Makefile自动生成工具-----autotools的使用(详细)

    相信每个学习Linux的人都知道Makefile,这是一个很有用的东西,但是编写它是比较复杂,今天介绍一个它的自动生成工具,autotools的使用.很多GNULinux的的软件都是用它生成Makef ...

  3. boost asio io_service学习笔记

    构造函数 构造函数的主要动作就是调用CreateIoCompletionPort创建了一个初始iocp. Dispatch和post的区别 Post一定是PostQueuedCompletionSta ...

  4. Asp.NET调用百度翻译

    Asp.NET调用百度翻译,图示: HTML: <%@ Page Language="C#" AutoEventWireup="true" CodeFil ...

  5. Get Cordova Ready for Grunt and CoffeeScript

    Cordova, Grunt and Coffee You may reference to below if you deside to work with coffee instead of Ja ...

  6. (WinForm)文件夹状态监控,最小化到托盘,开机自启动

    原文 (WinForm)文件夹状态监控,最小化到托盘,开机自启动 . 文件夾監控(監測文件夾中的文件動態): //MSDN上的例子 public class Watcher { public stat ...

  7. JavaScript移除数组元素

    //数组移除长度方法 var array=[]; array[0]="张三"; array[1]="李四"; array[2]="王五"; ...

  8. ORACLE 五种表的优缺点总结

    ORACLE 五种表的优缺点总结: 1.普通表(heap table):适合大部分设计场景,有长处也有缺点. 长处: a,语法简单方便 b,适合大部分场景 缺点: a,更新日志开销较大 b,Delet ...

  9. Delphi 获取网站验证码的图片

    uses ActiveX,ComObj; procedure TfrmMain.FormCreate(Sender: TObject); begin OleInitialize(nil); end; ...

  10. 自适应滤波器(Adaptive Filter)

    ======= Wikipedia的解释 ======= 自适应滤波器是能够根据输入信号自动调整性能进行数字信号处理的数字滤波器.作为对比,非自适应滤波器有静态的滤波器系数,这些静态系数一起组成传递函 ...