在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
前述: 第一次发表文章,不过是对数据库简单的封装,主要是阐述下思路。那么在上篇文章,在大家的指导下和提出意见,并自己对代码进行了思考。在这两天我重构了新的框架,我觉得我写的可以称得上框架,为什么?请大家往下看。不过在项目中没有很多注释。笔者除了课余学习时候,大部分时间在完成学校的功课,没有许多时间,所以也就偷下懒,请大家体谅。 这次框架分为几个部分:拼接数据库语句、数据库执行、数据库连接控制、异常类、用户使用的DbHelper。等下我回用文字和图还分析这个部分。经过重构后,类增多了,而且能够极大的支持开闭原则,我应该说就是与实际数据库无关,而且在上层使用中,不需要在引用system.Data.SqlClient这样实际访问的东西。虽然笔者只写了sql server的实例,但是如果扩展其他的数据库,也无需大规模的修改旧的代码,并且使用参数,能够防止注入攻击,支持事务。 好,先看怎么使用框架。 DbHelper helper = new DbHelper(); helper.createConnection("MyConnection","Data Source=CN-20161106HMJI;Initial Catalog=ShopInfo;Integrated Security=True",DbType.SQL); PlaceInfo model = helper.ExcuteString(o => o.From("PlaceInfo").Select().AndWhere("SAddNo", 1)).ToModel<PlaceInfo>(); Console.Read(); 上面是使用的一个例子,创建连接字符串,然后查询获取实例,已经没有打开数据库,或者是command的语句,使用起来是否十分简单,上面这句运行没有问题的,因为框架灵活度太大,测试的话不能所有都包含,这也是没办法,接下来跟着文章,一步步分析。 上次说,链式编程很好用,所以这次同样是链式编程,但这次更为强大。大家知道,dal的链式编程,主要是得到数据,而得到数据无非是对数据库查询语言进行封装。所以,在框架上,我封装了一个拼接语句的类,里面包含了我认为比较常用的数据库语句,支持order by。还有最强大的是,能够支持嵌套查询!也就是封装的sql语句可以是 select * from tableName where Id in(select id from tablename where ...)...这样子的。使用起来十分的方便。而且还有排序order by,等,可以在使用这套框架封装更使用的方法。 第二个新增的是连接控制,这个是这套框架的关键,因为框架不能占用内存,所以无论在拼接查询语句,还是在执行部分,都没有对数据库创建的语句,而是采用注入式,通过连接控制类,创建好数据库连接后,注入到所需要的部分中。而且这里控制了最耗性能的反射,对模型中的属性进行反射,都是耗时间,所以这里设置了缓存,对已经创建过对象的保存在这里,在拼接数据库语句或者是执行阶段需要用到,注入到其中,就可以省下时间。 第三个增加的是异常类,不过我封装的比较简单,里面就一个可重载的方法,这个是用来发生异常时候,用户能够自己设置发生错误之后应该做什么(比如保存到日志)而定的。 最后一个新增的是释放资源,因为对数据库连接,数据库连接数目比较少,但是command的数目在一般项目可就不是这样。可能大家为了方便,所以使用的时候尽情的new这样,那在我的框架设置了一个集合,专门存放command的,在用完后能够释放资源。因为考虑到在事务执行时候不能够对comand进行释放,所以在释放时候还做了判断。把有事务的command放到在事务执行后释放。
看完上边的功能,是不是觉得十分强大,因为这个框架理解和实现起来都不容易,所以笔者尽可能的让大家明白,知道我是怎么一步步完成的。 现在进入正题,先看下简单的结构图,看上去比较简单,不是我不会绘图,我在完成其他项目时候,都有完整的文档和图,因为现在没有太多时间,而且用软件画实在太慢了,所以大家将就的看吧。 上图就是我框架的结构图。箭头代表关联,从下到上,代表底层到用户使用的层次。框架是支持对数据库的扩展,上边三个部分写继承抽象类就是如此,因为这几个其实就是实际数据库会使用到,所以使用工厂模式,这样就能够扩展其他了。 好了,看完图,就开始讲解代码。 我第一步是从数据库拼接语句开始做的,因为这个虽然还不算底层,但是相对于其他可以独立,那么看下这一跪部分的类: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Dal { public interface IDbCode { /// <summary> /// 数据库执行表、视图、存储过程等对象 /// </summary> /// <param name="Object">名称</param> /// <returns></returns> IDbCode From(object Object); /// <summary> /// 查询 /// </summary> /// <param name="Fields">查询的字段</param> /// <returns></returns> IDbCode Select(string Fields = "*"); /// <summary> /// 删除 /// </summary> /// <returns></returns> IDbCode Delete(); /// <summary> /// 更新 /// </summary> /// <param name="model">更新对象</param> /// <param name="Fields">更新字段</param> /// <returns></returns> IDbCode Update(object model,string Fields = ""); /// <summary> /// 插入 /// </summary> /// <param name="model">插入对象</param> /// <param name="Fields">插入字段</param> /// <returns></returns> IDbCode Insert(object model,string Fields = ""); /// <summary> /// 与条件 /// </summary> /// <param name="Where">条件字符串</param> /// <returns></returns> IDbCode AndWhere(string Where); /// <summary> /// 与条件 /// </summary> /// <param name="Field">字段</param> /// <param name="Value">值</param> /// <returns></returns> IDbCode AndWhere(string Field,object Value); /// <summary> /// 与条件 /// </summary> /// <param name="Field">条件字段</param> /// <param name="Select">嵌套查询条件委托</param> /// <returns></returns> IDbCode AndWhere(string Field, Func<IDbCode, string> Select); /// <summary> /// 与条件 /// </summary> /// <typeparam name="T">值的类型</typeparam> /// <param name="Field">条件字段</param> /// <param name="Values">值</param> /// <returns></returns> IDbCode AndWhere<T>(string Field,List<T> Values); /// <summary> /// 或条件 /// </summary> /// <param name="Where">条件字符串</param> /// <returns></returns> IDbCode OrWhere(string Where); /// <summary> /// 或条件 /// </summary> /// <param name="Field">条件字段</param> /// <param name="Value">值</param> /// <returns></returns> IDbCode OrWhere(string Field, object Value); /// <summary> /// 或条件 /// </summary> /// <param name="Field">条件字段</param> /// <param name="Select">嵌套条件</param> /// <returns></returns> IDbCode OrWhere(string Field, Func<IDbCode, string> Select); /// <summary> /// 或条件 /// </summary> /// <typeparam name="T">值类型</typeparam> /// <param name="Field">条件字段</param> /// <param name="Values">值</param> /// <returns></returns> IDbCode OrWhere<T>(string Field, List<T> Values); /// <summary> /// Top 语句 /// </summary> /// <param name="topCount"></param> /// <returns></returns> IDbCode Top(int topCount); /// <summary> /// 排序从小到大 /// </summary> /// <param name="Field">排序字段</param> /// <returns></returns> IDbCode OrderByAsc(string Field); /// <summary> /// 排序从大到小 /// </summary> /// <param name="Field">排序字段</param> /// <returns></returns> IDbCode OrderByDesc(string Field); /// <summary> /// 多表查询时候必须加的条件 /// </summary> /// <param name="Fields">在两张表中的相同字段</param> /// <returns></returns> IDbCode ForMulTable(string Fields); string ToString(); /// <summary> /// 清空缓存 /// </summary> /// <returns></returns> IDbCode Clear(); IDbCode CreateCode(string sql); object Paras { get; } void Dispose(); } } 继承它的类: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Data.SqlClient; using System.Reflection; namespace Dal { public class SQLCode :IDbCode { string Object; StringBuilder ExcuteString = new StringBuilder(); List<SqlParameter> paras; Dictionary<string, List<PropertyInfo>> pro; static string[] s = { "select", "delect", "update", "insert" }; public SQLCode() { paras = new List<SqlParameter>(); } public SQLCode(Dictionary<string, List<PropertyInfo>> pro) { paras = new List<SqlParameter>(); this.pro = pro; } public SQLCode(List<SqlParameter> paras, Dictionary<string, List<PropertyInfo>> pro) { this.paras = paras; this.pro = pro; } public IDbCode From(object Object) { Type t = Object.GetType(); if(t.Name.ToLower().Equals("string")) { this.Object = Object.ToString(); }else { this.Object = t.Name; } return this; } public IDbCode Select(string Fields = "*") { if (this.Object.Length <= 0) return this; if (!Check(0)) return this; ExcuteString.AppendLine("select " + Fields +" from "+ this.Object); ExcuteString.AppendLine(" where 1 = 1 "); return this; } bool Check(int Type) { int flag = 0; string b = ExcuteString.ToString(); for (int i = 0; i < s.Length; i++) if(i!=Type) flag += b.Contains(s[i]) ? 1 : 0; return flag == 0; } public IDbCode Delete() { if (Object.Length <= 0) return this; if (!Check(1)) return this; ExcuteString.AppendLine("delete " + this.Object); ExcuteString.AppendLine(" where 1 = 1 "); return this; } public IDbCode Update(object model, string Fields = "") { if (this.Object.Length <= 0) return this; if (!Check(2)) return this; Type t = model.GetType(); if (t.Name != Object) return this; ExcuteString.AppendLine("update "+this.Object +" set "); List<PropertyInfo> p; if(pro.ContainsKey(t.Name)) { p = pro[t.Name]; }else { p = t.GetProperties().ToList(); pro.Add(t.Name, p); } string f = ""; if(Fields.Length==0) { p.ForEach(o => { f += o.Name + " = @" + o.Name; paras.Add(new SqlParameter(o.Name, o.GetValue(model, null))); }); }else { string[] a = Fields.Split(','); p.ForEach(o => { if (a.Contains(o.Name)) { f += o.Name + " = @" + o.Name + ","; paras.Add(new SqlParameter(o.Name, o.GetValue(model, null))); } }); } ExcuteString.AppendLine(f); ExcuteString.AppendLine("where 1 = 1"); return this; } public IDbCode Insert(object model, string Fields = "") { if (this.Object.Length <= 0) return this; if (!Check(3)) return this; Type t = model.GetType(); if (t.Name != Object) return this; ExcuteString.AppendLine("insert " + this.Object); List<PropertyInfo> p; if (pro.ContainsKey(t.Name)) { p = pro[t.Name]; } else { p = t.GetProperties().ToList(); pro.Add(t.Name, p); } string f = "( "; string f1 = "values( "; if (Fields.Length == 0) { p.ForEach(o => { f += o.Name+","; paras.Add(new SqlParameter(o.Name, o.GetValue(model, null))); f1 += "@" + o.Name + ","; }); } else { string[] a = Fields.Split(','); p.ForEach(o => { if (a.Contains(o.Name)) { f += o.Name + ","; paras.Add(new SqlParameter(o.Name, o.GetValue(model, null))); f1 += "@" + o.Name + ","; } }); } f = f.Remove(f.LastIndexOf(','), 1) + " ) "; f1 = f1.Remove(f1.LastIndexOf(','), 1) + " ) "; ExcuteString.AppendLine(f); ExcuteString.AppendLine(f1); return this; } public IDbCode AndWhere(string Where) { ExcuteString.AppendLine(" and " + Where); return this; } public IDbCode AndWhere(string Field, object Value) { ExcuteString.AppendLine(" and " + Field + " = @" + Field); paras.Add(new SqlParameter(Field, Value)); return this; } public IDbCode AndWhere(string Field, Func<IDbCode, string> Select) { ExcuteString.AppendLine(" and " + Field + " in " + Select(new SQLCode(this.paras,this.pro))); return this; } public IDbCode AndWhere<T>(string Field, List<T> Values) { string value = "("; Values.ForEach(o => { value += o + ","; }); ExcuteString.AppendLine(" and " + Field + " in " + value.Remove(value.LastIndexOf(','), 1) + ")"); return this; } public IDbCode OrWhere(string Where) { ExcuteString.AppendLine(" or " + Where); return this; } public IDbCode OrWhere(string Field, object Value) { ExcuteString.AppendLine(" or " + Field + " = @" + Field); paras.Add(new SqlParameter(Field, Value)); return this; } public IDbCode OrWhere(string Field, Func<IDbCode, string> Select) { ExcuteString.AppendLine(" or " + Field + " in " + Select(new SQLCode(this.paras,this.pro))); return this; } public IDbCode OrWhere<T>(string Field, List<T> Values) { string value = "("; Values.ForEach(o => { value += o + ","; }); ExcuteString.AppendLine(" or " + Field + " in " + value.Remove(value.LastIndexOf(','), 1) + ")"); return this; } public IDbCode Top(int topCount) { if (!ExcuteString.ToString().Contains(s[0])) return this; ExcuteString.Replace("select", "select top " + topCount +" "); return this; } bool CheckHasOrderBy() { return this.ExcuteString.ToString().Contains("order by"); } public IDbCode OrderByAsc(string Field) { if (CheckHasOrderBy()) ExcuteString.AppendLine("," + Field + " asc"); else ExcuteString.AppendLine(" order by " + Field+" asc"); return this; } public IDbCode OrderByDesc(string Field) { if (CheckHasOrderBy()) ExcuteString.AppendLine("," + Field + " desc"); else ExcuteString.AppendLine(" order by " + Field + " desc"); return this; } public IDbCode ForMulTable(string Fields) { List<string> tables = this.Object.Split(',').ToList(); Fields.Split(',').ToList().ForEach(o => { for (int i = 0; i < tables.Count - 1; i++) { ExcuteString.AppendLine(" and " + tables[i] + "." + o + " = " + tables[i + 1] + "." + o); } }); return this; } public override string ToString() { return this.ExcuteString.ToString(); } public IDbCode Clear() { pro.Clear(); return this; } public IDbCode CreateCode(string sql) { ExcuteString.AppendLine(sql); return this; } public object Paras { get { return this.paras; } } public void Dispose() { this.pro = null; } } }
|
请发表评论