两三个月前曾写过《重构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. TestNg JAVA 自动化单元测试框架Demo

    TestNg TestNg 是java的一个自动化单元测试框架 参考:http://testng.org/doc/index.html 环境准备 既然是java 的自动化单元测试框架,就必须要有jav ...

  2. MFC自绘(17篇)

    http://www.cnblogs.com/lidabo/category/477377.html

  3. WinSock - 建立有连接的通信

    1.建立服务端(发送端) (1)声明成员变量 public: CSocket m_sockSend; (2)每隔一秒钟发送一次数据 2.建立客户端(接收端) (1)声明成员变量 public: CSo ...

  4. bootstrap之WaitForIdle&amp;&amp;Clear

    (上篇文章写完才发现.说好的按顺序可是回头一看全然不是按顺序的)明明WaitForIdle才是第一个.哎,老了,后脑勺不行了. WaitForIdle package io.appium.androi ...

  5. Android本地视频播放器开发--视频解码

    在上一章Android本地视频播放器开发--SDL编译编译中编译出sdl的支持库,当时我们使用的2.0,但是有些api被更改了,所以在以下的使用者中我们使用SDL1.3的库,这个库我会传上源码以及编译 ...

  6. Unable to instantiate activity ComponentInfo或java.lang.ClassNotFoundException: com.ibright.herolegen

    不知道怎么回事,在libs中添加了jar包后,无法给jar包附加上源码,于是采取以下措施: 删除自动生成的依赖: 在Android Dependences目录上右击->Build Path -& ...

  7. Swift - 使用导航条和导航条控制器来进行页面切换

    通过使用导航条(UINavigationBar)与导航条控制器(UINavigationController)可以方便的在主页面和多层子页面之间切换.下面通过一个简单“组件效果演示”的小例子来说明如何 ...

  8. 所有CN_消息的说明

    Notification Message Corresponding WindowsConstant Message Description cn_CharToItem wm_CharToItem T ...

  9. Delphi的类型转换 good

    Delphi是一种强类型转换的语言.在VC中,赋值符用″=″,例如x=1;到了Delphi赋值符就变成了″:=″,例如x:=1. 从赋值时用符号″:=″而不用″=″,就隐约可见Delphi对类型匹配要 ...

  10. Servlet API中文版

    基本类和接口 一.javax.servlet.Servlet接口 servlet抽象集是javax.servlet.Servlet接口,它规定了必须由Servlet类实现由servlet引擎识别和管理 ...