這是一個簡單的ORM框架思路及雛形


  一直以來都有一個夢想,想用更少的代碼實現更多的功能。也在一些任職的公司看到過他們內部使用的一些ORM,確實很好很強大,但是個人覺得涉及知識面比較廣,不適合個人的理解和使用。最近突發奇想,想自己嘗試下,借助一些思路,自己寫一個簡單的、入門級的框架,所以便有了此文。此文這是一個雛形,實現了一個簡單的查詢效果,當然如果理解了,那么其他操作都是重復性的了(增加、刪除、修改)。

一些問題(僅針對本人)

1、如果采用剛入門的三層,代碼量太大,雖然可以使用一些工具來生成(T4等)。但是想實現動態查詢的參數化還是比較麻煩的,而且代碼重用性不高,幾乎每個文件實現的都是一模一樣的一些方法。

2、SQL的注入,本人以前的一些代碼就存在這樣的問題。

3、當然還有些問題就不在這里講了,以前用過三層的就知道了。 

 

解決

1、個人思路是把整個數據訪問全部剝離處理,根據不同的實體,對不同的表進行操作。數據訪問層中的方法全是公用的,傳入參數和實體(T)。即所有實體公用一個數據訪問層,不再像三層那樣一個實體,一個數據訪問類。

2、將對數據的所有操作全部封裝成參數話查詢(本文的IN操作沒有參數化)。

3、對業務邏輯的處理全部采用面向對象的形式操作。

 

代碼實例

1、動態的構造查詢語句參數化及參數列表

     private StringBuilder whereString;//SQL查詢條件
        private Dictionary<string, object> paramTable;//SQL參數列表
        private int KeyNum = 1;//參數標識
        private string tableName;//表名
        private string[] columnNames;//查詢列名 

        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="TableName">表名</param>
        /// <param name="ColumnNames">列名</param>
        public SelectString(string TableName,  params string[] ColumnNames)
        {
            if (paramTable == null) paramTable = new Dictionary<string, object>();
            if (whereString == null)
            {
                whereString = new StringBuilder();
                tableName = TableName;
                columnNames = ColumnNames;
            }
        }

        /// <summary>
        /// 獲取篩選的列名組成的字符串。
        /// </summary>
        /// <param name="columnNames">篩選的列名集合</param>
        /// <returns>列名組成的字符串</returns>
        private string GetColumns()
        {
            if (columnNames == null || columnNames.Length == 0) return "*";

            string[] cols = new string[columnNames.Length];
            for (int i = 0; i < columnNames.Length; i++)
            {
                cols[i] = string.Format("{0}", columnNames[i]);
            }

            return string.Join(",", cols);
        }

        /// <summary>
        /// and表達式
        /// </summary>
        /// <param name="FieldName">字段名稱</param>
        /// <param name="FieldValue">字段值</param>
        /// <param name="Operat">操作符</param>
        public void Add(string FieldName, object FieldValue, string Operat)
        {
            if (Operat == "in")
                whereString.AppendFormat(" and {0} {1} ({2})", FieldName, Operat, FieldValue);
            else
            {
                whereString.AppendFormat(" and {0} {1} {2}", FieldName, Operat, string.Format("@Key{0}", KeyNum));
                paramTable.Add(string.Format("@Key{0}", KeyNum), FieldValue);
                KeyNum++;
            }
        }

        /// <summary>
        /// or表達式
        /// </summary>
        /// <param name="FieldName">字段名稱</param>
        /// <param name="FieldValue">字段值</param>
        /// <param name="Operat">操作符</param>
        public void Or(string FieldName, object FieldValue, string Operat)
        {
            if (Operat == "in")
                whereString.AppendFormat(" or {0} {1} ({2})", FieldName, Operat, FieldValue);
            else
            {
                whereString.AppendFormat(" or {0} {1} {2}", FieldName, Operat, string.Format("@Key{0}", KeyNum));
                paramTable.Add(string.Format("@Key{0}", KeyNum), FieldValue);
                KeyNum++;
            }
        }

        /// <summary>
        /// SQL參數表
        /// </summary>
        public Dictionary<string, object> ParamsTable
        {
            get { return paramTable; }
            set { paramTable = value; }
        }

        /// <summary>
        /// SQL查詢條件
        /// </summary>
        public string QueryString
        {
            get
            { 
                if (whereString.Length > 0)
                {

                    return string.Format("select {2} from {0} where 1=1 {1}", tableName, whereString, GetColumns());
                }
                else
                    return string.Format("select {1} from {0} where 1=1", tableName, GetColumns());
            }
        }

 2、將構造好的參數傳入,獲取及處理數據,然后返回。

     /// <summary>
        /// 獲取數據
        /// </summary>
        /// <param name="Sql">SQL語句</param>
        /// <param name="paramTable">參數列表</param>
        /// <returns></returns>
        public List<T> GetList<T>(string Sql, Dictionary<string, object> paramTable)
        {
            List<T> ListT = new List<T>();
            using (SqlConnection Connection = new SqlConnection(SqlString))
            {
                Connection.Open();
                using (SqlCommand Command = new SqlCommand())
                {
                    Command.Connection = Connection;
                    Command.CommandText = Sql;
                    //添加參數
                    foreach (KeyValuePair<string, object> ItemDictionary in paramTable)
                    {
                        Command.Parameters.Add(new SqlParameter() { ParameterName = ItemDictionary.Key, Value = ItemDictionary.Value });
                    }
                    SqlDataReader DataReader = Command.ExecuteReader(CommandBehavior.CloseConnection);
                    //反射賦值
                    PropertyInfo[] propertys = typeof(T).GetProperties();
                    try
                    {
                        //獲取需要返回的列
                        List<string> ListColumns = DataReader.GetSchemaTable().Rows.Cast<DataRow>().Select(p => p.ItemArray[0].ToString()).ToList();
                        while (DataReader.Read())
                        {
                            T t = System.Activator.CreateInstance<T>();
                            foreach (PropertyInfo item in propertys)
                            {
                                if (ListColumns.Contains(item.Name))
                                    if (DataReader[item.Name] != DBNull.Value)
                                        item.SetValue(t, DataReader[item.Name], null);
                            }
                            ListT.Add(t);
                        }
                    }
                    catch (SqlException ex)
                    {
                        throw ex;
                    }
                    finally
                    {
                        //切記關閉
                        DataReader.Close();
                    }
                }
            }
            return ListT;
        }

 

 3、使用(構造實體類)

        /// <summary>
        /// 表名(務必保持與數據庫一致)
        /// </summary>
        public static string TableName = "Users";

        #region 字段名(務必保持與數據庫一致)
        /// <summary>
        /// 用戶編號
        /// </summary>
        public static string C_FUserID = "FUserID"; 
        #endregion

        #region 屬性
        /// <summary>
        /// 用戶編號
        /// </summary>
        public int FUserID { get; set; }

 

使用實例

            //實例化查詢構造器
            SelectString QuerySql = new SelectString(Users.TableName);
            QuerySql.Add(Users.C_FUserID, 1000, Operat.DengYu);
            QuerySql.Add(Users.C_UName, "張三", Operat.Like);
            QuerySql.Or(Users.C_FUserID, "100,110,120,130,140,150,160,170", Operat.In);

            //獲取及填充數據
            SqlHelper SqlHelper = new SqlHelper();
            List<Users> ListUser = SqlHelper.GetList<Users>(QuerySql.QueryString, QuerySql.ParamsTable);

 

  這里面涉及的知識面也不是特別廣,大家應該都能看的懂。其實就是在實體類中多封裝一些信息,然后通過一個構造器,構造出需要執行的SQL語句(參數化)和參數集合,然后在傳入底層,底層根據傳入進來的SQL及參數集合。獲取數據,然后再把同時一起傳入進來的類型T,根據反射動態賦值,然后再返回上去。這樣便簡單的實現了一個動態參數化查詢,只需要構造好實體類,然后查詢構造器,組裝好SQL和參數,傳入同一個底層方法,即可獲取不同表中的數據。此文只說到簡單的單表操作,可自行拓展。其他操作都可以照這種思路進行封裝哦,把平時需要使用到的一些跟數據庫打交道的方法都封裝好,然后使用的時候只需要調用就好了。這樣是不是使用起來比較方便呢?

 

  到此本文就寫完了,其實原理都很簡單的,本人只是抱着分享的態度,高手請多多指教。源碼將於晚上發布到這里、這里喔(其實源碼差不多都在這里了)。


免責聲明!

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



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