当前位置:Gxlcms > 数据库问题 > C# .NET更智能的数据库操作的封装完整版(重构)

C# .NET更智能的数据库操作的封装完整版(重构)

时间:2021-07-01 10:21:17 帮助过:15人阅读

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

  如果有看过上次的文章,那么就知道这里部分方法用到反射,获取其中的属性来拼写语句。没什么难的,大家看到里面有许多的if条件,是我避免在链式组合时候,用户随便乱时候而设置的。这部分都是对字符串处理。

  第二部分是执行语句,这个相信大家写多了,先给代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace Dal
{
    public interface IDbExcute
    {
        T ToModel<T>(IDbCode code, CommandType type = CommandType.Text)
            where T : class,new();

        List<T> ToList<T>(IDbCode code,CommandType type = CommandType.Text)
            where T : class,new();

        object ToResult(IDbCode code, CommandType type = CommandType.Text);

        int ExcuteResult(IDbCode code, CommandType type = CommandType.Text);

        DataTable ToDataTable(IDbCode code, CommandType type = CommandType.Text);

        DataSet ToDataSet(IDbCode code, CommandType type = CommandType.Text);

        void OpenConnection();
        void CloseConnection();

        void Dispose(object tran);

        void BeginTransation(string Name);
        void Commit();
        void RollBack();
    }
}

上面就是支持整个框架的执行方法

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 SQLExcute : IDbExcute
    {
        SqlConnection conn;
        Dictionary<string, List<PropertyInfo>> pro;
        Dictionary<string, SqlCommand> command;
        SqlTransaction tran = null;
         
        public SQLExcute(SqlConnection conn, Dictionary<string, List<PropertyInfo>> pro)
        {
            this.conn = conn;
            this.pro = pro;
            command = new Dictionary<string, SqlCommand>();
        }

        public List<T> ToList<T>(IDbCode code,CommandType type = CommandType.Text)
            where T:class,new()
        {
            List<T> list = new List<T>();
            string name = DateTime.Now.ToString();
            command.Add(name, new SqlCommand());
            SqlCommand com = command[name];
            com.Connection = conn;
            com.CommandText = code.ToString();
            com.CommandType = type;
            setCommand(com, (List<SqlParameter>)code.Paras);


            Type t = typeof(T);
            List<PropertyInfo> pros;
            if(pro.ContainsKey(t.Name))
            {
                pros = pro[t.Name];
            }else
            {
                pros = t.GetProperties().ToList();
                pro.Add(t.Name, pros);
            }

            try
            {
                this.OpenConnection();
                using (SqlDataReader reader = com.ExecuteReader())
                {
                    while(reader.Read())
                    {
                        T model = new T();
                        pros.ForEach(o =>
                        {
                            if(ReaderExists(reader,o.Name))
                            {
                                o.SetValue(model, reader[o.Name], null);
                            }
                        });
                        list.Add(model);
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                this.Dispose(name);
                this.CloseConnection();
            }
            
            return list;
        }

        public bool ReaderExists(SqlDataReader reader, string columnName)
        {
            //reader.GetSchemaTable().DefaultView.RowFilter = "ColumnName= ‘" + columnName + "‘";
            //return (reader.GetSchemaTable().DefaultView.Count > 0);
            return reader.GetSchemaTable().Select("ColumnName=‘" + columnName + "").Length > 0;
        }
        public void Dispose(string name)
        {
            if(command.ContainsKey(name))
            {
                SqlCommand com = command[name];
                command.Remove(name);
                com.Dispose();
            }
            if (command.Count <= 0)
                this.CloseConnection();
        }

        public void Dispose(object tran)
        {
            List<string> list = command.Keys.ToList();
            list.ForEach(o =>
            {
                if(command[o].Transaction!=null&&command[o].Transaction==(SqlTransaction)tran)
                {
                    this.Dispose(o);
                }
            });
        }

        public object ToResult(IDbCode code, CommandType type = CommandType.Text)
        {
            string name = DateTime.Now.ToString();
            command.Add(name, new SqlCommand());
            SqlCommand com = command[name];
            com.Connection = conn;
            com.CommandText = code.ToString();
            com.CommandType = type;
            setCommand(com, (List<SqlParameter>)code.Paras);


            object result =null;
            try
            {
                th                    

人气教程排行