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

 

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

posted @ 2013-03-01 15:44  CHild.  阅读(3178)  评论(11编辑  收藏  举报