c# 轻量级ORM框架 之 WhereHelper (二)
上篇文章发布了一些设计orm框架基层的和实现,有朋友提出WhereHelper是亮点,能被认可我表示高兴.
我就把WhereHelper设计思想和代码公开下.
WhereHelper 的概念就是再拼接where 条件,为了能兼容各种数据库和参数化查询,故封装了该对象.
首先根据我的框架结构:
1.Common库
这里主要定义了,所有层都访问的类型及常用方法,因为是介绍WhereHelper的实现,对其它就不做详细解释了.
WhereHelper定义到这一层是想着UI会用到该查询,故把该类型的定义放到Common里
2.DataAccess
该层是操作数据库的一些方法封装.
在Common里的WhereHelper它是抽象的(其实完全可以是接口),且构造函数为
WhereHelper的实现类均放在DataAccess里,而且它的实现类构造函数都为 internal ,这个是为了实现只有我的Dal具体类(SQLDalBase,OracleDalBase,等等)知道它应该创建什么类型的具体WhereHelper对象,其实在DalBase里定义了WHereHelper的工厂.
不能让调用者直接创建.否则整个系统改变数据库时,就意味着要改变它创建的具体对象.
以下是WHereHelper的代码具体实现
public abstract class WhereHelper { #region 构造函数 protected WhereHelper() { _WhereText = new StringBuilder(); _ParamDict = new Dictionary<string, object>(); } protected WhereHelper(string paramNameKey) : this() { _ParamNameKey = paramNameKey; } protected WhereHelper(WhereHelper wh) : this() { this._LastParamIndex = wh._LastParamIndex; this._ParamDict = wh._ParamDict; this._WhereText = wh._WhereText; this._ParamNameKey = wh._ParamNameKey; } #endregion #region 重写ToString public override string ToString() { return _WhereText.ToString(); } #endregion #region 字段 string _ParamNameKey; StringBuilder _WhereText; Dictionary<string, object> _ParamDict; int _LastParamIndex = -1; #endregion #region 属性 /// <summary> /// 返回当前对象所有产品参数集合字典,key:参数数名(包含@),value:参数值 /// </summary> public Dictionary<string, object> ParamDict { get { return _ParamDict; } } /// <summary> /// 返回当前生成where文本 /// </summary> public StringBuilder WhereText { get { return _WhereText; } } #endregion #region 外部方法 /// <summary> /// 增加查询参数,并输出参数名,参数名会根据LastParamIndex递增 /// </summary> /// <param name="v">参数值</param> /// <returns>返回参数名</returns> protected string AddParam(object v) { _LastParamIndex++; string paramName = string.Format("@P_{1}{0}", _LastParamIndex, _ParamNameKey); _ParamDict.Add(paramName, v); return paramName; } /// <summary> /// 清除文本内容和参数内容 /// </summary> public void Clear() { _ParamDict.Clear(); _WhereText.Remove(0, _WhereText.Length); } /// <summary> /// 当前where文本增加字符(通常该值是 字段名 ),返回当前对象 /// </summary> public virtual WhereHelper Add(string str) { this._WhereText.AppendFormat(" {0} ", str); return this; } /// <summary> /// 比较符,等于 "=" /// </summary> public virtual WhereHelper Equal(object v) { this._WhereText.AppendFormat(" = {0}", AddParam(v)); return this; } /// <summary> /// 比较符,不等于 "!=" /// </summary> public virtual WhereHelper EqualNot(object v) { _WhereText.AppendFormat(" <> {0}", AddParam(v)); return this; } /// <summary> /// 比较符,大于 ">" /// </summary> public virtual WhereHelper GreaterThan(object v) { this._WhereText.AppendFormat(" > {0}", AddParam(v)); return this; } /// <summary> /// 比较符,小于 /// </summary> public virtual WhereHelper LessThan(object v) { this._WhereText.AppendFormat(" < {0}", this.AddParam(v)); return this; } /// <summary> /// 比较符,大于等于 /// </summary> public virtual WhereHelper GreaterThenEqual(object v) { this._WhereText.AppendFormat(" >= {0}", this.AddParam(v)); return this; } /// <summary> /// 比较符,小于等于 /// </summary> public virtual WhereHelper LessThanEqual(object v) { this._WhereText.AppendFormat(" <= {0}", this.AddParam(v)); return this; } /// <summary> /// 比较符,In,参数为某范围内的比较值 /// </summary> public virtual WhereHelper In(params object[] inArgs) { this._WhereText.Append(" in ("); for (int i = 0; i < inArgs.Length; i++) { _WhereText.Append(AddParam(inArgs[i])); if (i < inArgs.Length - 1) { _WhereText.Append(","); } } this._WhereText.Append(" )"); return this; } /// <summary> /// 比较符,NotIn /// </summary> public virtual WhereHelper NotIn(params object[] inArgs) { this._WhereText.Append(" not in ("); for (int i = 0; i < inArgs.Length; i++) { _WhereText.Append(AddParam(inArgs[i])); if (i < inArgs.Length - 1) { _WhereText.Append(","); } } this._WhereText.Append(" )"); return this; } /// <summary> /// 比较符 left Like %{0} /// </summary> public virtual WhereHelper LikeLeft(string v) { string addParam = AddParam(string.Format("%{0}", v)); this._WhereText.AppendFormat(" like {0}", addParam); return this; } /// <summary> /// 比较符 right like {0}% /// </summary> public virtual WhereHelper LikeRight(string v) { string addParam = AddParam(string.Format("{0}%", v)); this._WhereText.AppendFormat(" like {0}", addParam); return this; } /// <summary> /// 比较符 full like /// </summary> public virtual WhereHelper LikeFull(string v) { string addParam = AddParam(string.Format("%{0}%", v)); this._WhereText.AppendFormat(" like {0}", addParam); return this; } /// <summary> /// 增加一个左括号 "(" /// </summary> public virtual WhereHelper BracketLeft() { this._WhereText.AppendFormat("("); return this; } /// <summary> /// 增加一个左括号"(",再加一个字符串(通常是一个字段) /// </summary> public virtual WhereHelper BracketLeft(string str) { this._WhereText.AppendFormat("("); this._WhereText.AppendFormat(str); return this; } /// <summary> /// 增加一个右括号 ")" /// </summary> public virtual WhereHelper BracketRight() { this._WhereText.Append(")"); return this; } /// <summary> /// 增加连接符 "and" /// </summary> public virtual WhereHelper And() { And(string.Empty); return this; } /// <summary> /// 增加连接符 "and" /// </summary> public virtual WhereHelper And(string str) { if (this._WhereText.Length > 0) { this._WhereText.Append(" and "); } this._WhereText.Append(str); return this; } /// <summary> /// 增加连接符 "or" /// </summary> public virtual WhereHelper Or() { Or(string.Empty); return this; } /// <summary> /// 增加连接符"or",再加一个字符串(通常是一个字段) /// </summary> public virtual WhereHelper Or(string str) { if (this._WhereText.Length > 0) { this._WhereText.Append(" or "); } this._WhereText.Append(str); return this; } #endregion }
代码实现比较简单.
这个抽象类有了具体实现,如果再使用非sqlserver数据库时报错了(sql语法),那么就去DataAccess中找到它对应的具体类,去重写它的方法.
该类的所有public方法都返回了 this,也就是说,你"点"把它始终是一个对象.
拼接方式也非常灵活,可以直接拼写sql文(但不建议)它会给迁移数据库带来隐患.
至于参数的名字,只要你是一个WHereHleper对象,它是肯定不会重复的,如果你要拼接另外一个未知的WHereHelper到当前对象你可以用它的另一个构造(用到的几率很小)
举个例子吧:
sql where条件: 姓名='张三' and 年龄 > 20 and 年龄<30 and (性别=男 or 性别=女 )
代码如下:
WhereHelper wh1 = _BllObj.CreateWhereHelper(); wh1.Add("姓名") .Equal("张三") .And("年龄") .GreaterThan(20) .And("年龄") .LessThan(30) .And() .BracketLeft("性别") .Equal("男") .Or("性别") .BracketRight();
为了格式好看,我把它每次"点"分成了一行(这个看起来确实有点像jquery的感觉);
好了,这个实现大概先说这么多,如果有什么问题欢迎留言.
有人回复,我才有写下去的动力.
关于我的orm框架,第一篇,其实是实现的根本.
值的写出来或许还有DBHelper的实现,通常初学者都会写一个具体的如:SQL Server 数据的 SQLHelper ,当你写另外一个数据库支持的时候就会发现你的重复代码很多,就会想起我们亲爱的"面向对象"了.