C# .NET更智能的數據庫操作的封裝完整版(重構)


前述:

  第一次發表文章,不過是對數據庫簡單的封裝,主要是闡述下思路。那么在上篇文章,在大家的指導下和提出意見,並自己對代碼進行了思考。在這兩天我重構了新的框架,我覺得我寫的可以稱得上框架,為什么?請大家往下看。不過在項目中沒有很多注釋。筆者除了課余學習時候,大部分時間在完成學校的功課,沒有許多時間,所以也就偷下懶,請大家體諒。

  這次框架分為幾個部分:拼接數據庫語句、數據庫執行、數據庫連接控制、異常類、用戶使用的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;
        }
    }
}

  如果有看過上次的文章,那么就知道這里部分方法用到反射,獲取其中的屬性來拼寫語句。沒什么難的,大家看到里面有許多的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
            {
                this.OpenConnection();
                result = com.ExecuteScalar();
            }
            catch (Exception ex)
            {
                DoException();
                throw ex;
            }finally
            {
                this.Dispose(name);
                this.CloseConnection();
            }
            
            return result;
        }

        private void DoException()
        {
            new DbException().Done();
        }

        public int ExcuteResult(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);


            int result = 0;
            try
            {
                this.OpenConnection();
                if (tran != null)
                    com.Transaction = (SqlTransaction)tran;
                result = com.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                DoException();
                throw ex;
            }
            finally
            {
                if (tran == null)
                    Dispose(name);
                this.CloseConnection();
            }
            return result;
        }

        public System.Data.DataTable ToDataTable(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);

            DataTable dt = new DataTable();
            try
            {
                using(SqlDataAdapter adapter = new SqlDataAdapter(com))
                {
                    adapter.Fill(dt);
                }
            }
            catch (Exception ex)
            {
                DoException();
                throw ex;
            }finally
            {
                Dispose(name);
            }

            return dt;
        }

        public void setCommand(SqlCommand com,List<SqlParameter> paras)
        {
            paras.ForEach(o =>
            {
                com.Parameters.Add(o);
            });
        }


        public System.Data.DataSet ToDataSet(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);

            DataSet dt = new DataSet();
            try
            {
                using (SqlDataAdapter adapter = new SqlDataAdapter(com))
                {
                    adapter.Fill(dt);
                }
            }
            catch (Exception ex)
            {
                DoException();
                throw ex;
            }
            finally
            {
                Dispose(name);
            }

            return dt;
        }

        public T ToModel<T>(IDbCode code, CommandType type = CommandType.Text)
            where T : class,new()
        {
            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> p = null;
            if(pro.ContainsKey(t.Name))
            {
                p = pro[t.Name];
            }else
            {
                p = t.GetProperties().ToList();
                pro.Add(t.Name, p);
            }
            T model = new T();

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

            return model;
        }

        public void OpenConnection()
        {
            if (this.conn.State != ConnectionState.Open)
                this.conn.Open();
        }

        public void CloseConnection()
        {
            command.Values.ToList().ForEach(o =>
            {
                if (o.Transaction != null)
                    return;
            });

            if (this.conn.State != ConnectionState.Closed)
                this.conn.Close();
        }

        public void BeginTransation(string Name)
        {
            tran = conn.BeginTransaction(Name);
        }

        public void Commit()
        {
            tran.Commit();
            Dispose(tran);
            tran = null;
        }

        public void RollBack()
        {
            tran.Rollback();
            Dispose(tran);
            tran = null;
        }
    }
}

  具體類中,主要設計了最重要的執行方法外,還像剛開始所述,設置了List,就是用來存放command對象,在執行完成時候時候它會自己釋放。跟這個類配合使用的是異常類:

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

namespace Dal
{
    public class DbException
    {
        public virtual void Done()
        {

        }
    }
}

只有短短幾句話,這就是用於使用者想發生異常想它干什么而設置的。

其實封裝到這里,整個框架的支持已經形成,但是用戶不能直接操作底層,而且還需要怎么對數據庫進行實例,所以還要對上進行封裝,下一步,往上走,數據庫實例部分。

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

namespace Dal
{
    public interface IDbInstance
    {
        /// <summary>
        /// 數據庫名稱
        /// </summary>
        string Name
        {
            get;
        }

        /// <summary>
        /// 獲取執行語句類
        /// </summary>
        IDbExcute Excute
        {
            get;
        }

        /// <summary>
        /// 獲取連接字符串
        /// </summary>
        string ConnectionString
        {
            get;
        }
        /// <summary>
        /// 開啟事務
        /// </summary>
        /// <param name="TranName">事務名稱</param>
        /// <returns></returns>
        object getTransation(string TranName);

        /// <summary>
        /// 獲取拼寫字符串類
        /// </summary>
        IDbCode Code
        {
            get;
        }
    }
}

實現它的具體類包含所有的底層的操作,其實就是可以說是一個數據庫實例了,創建一個就相當於一個數據庫。里面將上邊封裝的類都在這里使用。

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 SQLInstance :IDbInstance
    {
        private SqlConnection conn;
        private IDbExcute excute;
        Dictionary<string, List<PropertyInfo>> pro;
        private string name;
        private string connectionString;
        private SqlTransaction tran = null;
        public SQLInstance(string Name,Dictionary<string,List<PropertyInfo>> pro, string ConnectionString)
        {
            this.name = Name;
            this.connectionString = ConnectionString;
            conn = new SqlConnection(ConnectionString);
            this.pro = pro;
            excute = new SQLExcute(conn,pro);
        }

        public string Name
        {
            get
            {
                return this.name;
            }
        }
        public IDbExcute Excute
        {
            get
            {
                return this.excute;
            }
        }

        public string ConnectionString
        {
            get
            {
                return this.connectionString;
            }
        }

        public object getTransation(string TranName)
        {
            return this.conn.BeginTransaction(TranName);
        }

        public IDbCode Code
        {
            get
            {
                return new SQLCode(pro);
            }
        }
    }
}

接下來是控制連接的類:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace Dal
{
    public class DbControl
    {
        //數據庫服務
        private static Dictionary<string, IDbInstance> Server = new Dictionary<string, IDbInstance>();
        //存放緩存
        private static Dictionary<string, List<PropertyInfo>> pro = new Dictionary<string, List<PropertyInfo>>();
        private static DbControl control = new DbControl();
        public static DbControl getInstance()
        {
            return control;
        }
        private DbControl()
        {

        }
        public IDbInstance createInstance(string Name,string ConnectionString,string type)
        {
            string nspace = typeof(IDbInstance).Namespace;
            Type t = Type.GetType(nspace + "." + type);
            object obj = Activator.CreateInstance(t, new object[] { Name, pro, ConnectionString });
            
            IDbInstance instance = obj as IDbInstance;

            Server.Add(Name, instance);

            return instance;
        }

        public IDbInstance this[string Name]
        {
            get
            {
                if (Server.ContainsKey(Name))
                    return Server[Name];
                else
                    return null;
            }
        }
    }
}

這里算是頂層的類,最主要就是存放數據庫和緩存對象。也許會好奇如果存放數據庫,還可以理解,但是放着模型對象的緩存,這是為什么?因為在字符連接,還有具體執行數據庫語句時候都會使用到。而且,不僅這個數據庫,別的數據庫也會使用到,雖然在一個大項目可能用多個數據庫,但是他們使用到項目里的模型是一致的吧,因此,將緩存設置在這里,最好不過。而且整個框架只有這一份,其他地方注入使用,就不會耗內存了。

最后就是用戶使用的部分,這部分已經屏蔽掉許多底層的部分,只留下通用方法。這些都已經封裝好了,直接在這里調用就可以。

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

namespace Dal
{
    public class DbHelper
    {
        private IDbInstance instance;
        private string Name;
        private DbControl control;
        private IDbCode Code;

        public DbHelper()
        {
            control = DbControl.getInstance();
        }

        public DbHelper createConnection(string Name, string ConnectionString, string type)
        {
            this.Name = Name;
            instance = control.createInstance(Name, ConnectionString, type);
            return this;
        }

        public DbHelper ExcuteString(Func<IDbCode,IDbCode> Fun)
        {
            Code = Fun(this.instance.Code);
            return this;
        }

        public DbHelper createTransation(string Name)
        {
            this.instance.Excute.BeginTransation(Name);
            return this;
        }

        public DbHelper Rollback()
        {
            this.instance.Excute.RollBack();
            return this;
        }
        public DbHelper Commit()
        {
            this.instance.Excute.Commit();
            return this;
        }


        public T ToModel<T>(CommandType Type = CommandType.Text)
            where T:class,new()
        {
            if (this.Code == null)
                return null;
            return this.instance.Excute.ToModel<T>(this.Code,Type);
        }
        List<T> ToList<T>(CommandType Type = CommandType.Text)
            where T:class,new()
        {
            if (this.Code == null)
                return null;
            return this.instance.Excute.ToList<T>(this.Code, Type);
        }
        object ToResult(CommandType Type = CommandType.Text)
        {
            if (this.Code == null)
                return null;
            return this.instance.Excute.ToResult(this.Code, Type);
        }
        int ExcuteResult(CommandType Type = CommandType.Text)
        {
            if (this.Code == null)
                return -1;
            return this.instance.Excute.ExcuteResult(this.Code, Type);
        }
        DataTable ToDataTable(CommandType Type = CommandType.Text)
        {
            if (this.Code == null)
                return null;
            return this.instance.Excute.ToDataTable(this.Code, Type);
        }
        DataSet ToDataSet(CommandType Type = CommandType.Text)
        {
            if (this.Code == null)
                return null;
            return this.instance.Excute.ToDataSet(this.Code, Type);
        }
    }
}

 

  結束:快要熄燈了,沒辦法在寫文章。如果大家對框架有什么不明白,可以在下面評論區問我。這就是更新之后的框架,我覺得還是蠻好用的,雖然還沒經過嚴密的檢測。有什么問題,大家也可以指導下,我也在學習中~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM