• 这是一个简单的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和参数,传入同一个底层方法,即可获取不同表中的数据。此文只说到简单的单表操作,可自行拓展。其他操作都可以照这种思路进行封装哦,把平时需要使用到的一些跟数据库打交道的方法都封装好,然后使用的时候只需要调用就好了。这样是不是使用起来比较方便呢?

      到此本文就写完了,其实原理都很简单的,本人只是抱着分享的态度,高手请多多指教。源码将于晚上发布到这里、这里喔(其实源码差不多都在这里了)。

    作者:LyIng.Net
    出处:http://www.cnblogs.com/jiangbiao/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    遇到容易忘记的问题(二)
    遇到容易忘记的问题(三)
    遇到容易忘记的问题(一)
    UC浏览器input文本框输入文字回车键自动提交
    弹框在当前屏幕完全居中的方法
    遇到的浏览器问题总结
    HTML常用的特殊符号&前端使用的标点符号
    小程序里的页面跳转
    移除所有子视图
    UIView用户事件响应
  • 原文地址:https://www.cnblogs.com/jiangbiao/p/2938890.html
Copyright © 2020-2023  润新知