数据持久化辅助类

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

namespace CR
{
    #region 定义的特性
    /// <summary>
    /// 定义实体与数据库的映射关系 (tabName:表名  primaryKey:主键列名  autoPrimarykey:主键是否自动编号)
    /// 设计者 yixueli 2011-10-8
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] // multiuse attribute
    public class Tab : Attribute  //从Attribute 继承,写一个自定义属性
    {
        /// <summary>
        /// 定义实体与数据库的映射关系 (tabName:表名  primaryKey:主键列名  autoPrimarykey:主键是否自动编号)
        /// </summary>
        public Tab(string tabName, string primaryKey, bool autoPrimarykey)
        {
            this.TabName = tabName;
            this.Primarykey = primaryKey;
            this.AutoPrimarykey = autoPrimarykey;
        }

        /// <summary>
        /// 表名
        /// </summary>
        public string TabName { get; set; }

        /// <summary>
        /// 主键名
        /// </summary>
        public string Primarykey { get; set; }

        /// <summary>
        /// 主键是否为自动编号,即不需要程序生成
        /// </summary>
        public bool AutoPrimarykey { get; set; }

    }


    /// <summary>
    /// 指定该属性绑定的字段名
    /// </summary>
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
    public class Bind : Attribute
    {
        /// <summary>
        /// 指定该属性绑定的字段名
        /// </summary>
        /// <param name="name"></param>
        public Bind(string name)
        {
            this.Name = name;
        }

        /// <summary>
        /// 绑定名
        /// </summary>
        public string Name { get; set; }

    }
    #endregion

    /// <summary>
    /// 数据持久化相关操作,可用于简单的实体与数据库对象的转换,简单的增删改查操作
    /// </summary>
    public class ORM
    {

        #region 实体属性反射
        /// <summary>
        /// 获取实体tab特性
        /// </summary>
        private static Tab GetTabAttribute(object entity)
        {
            var tabs = entity.GetType().GetCustomAttributes(typeof(Tab), true);
            return (Tab)tabs[0];
        }

        private static Tab GetTabAttribute<T>() where T : new()
        {
            var tabs = typeof(T).GetCustomAttributes(typeof(Tab), true);
            return (Tab)tabs[0];
        }

        /// <summary>
        /// 获取属性对应的数据库字段
        /// </summary>
        private static string GetBindName(PropertyInfo property)
        {
            //如果定义了bind属性,则采用bind的定义,否则是属性名
            var bind = property.GetCustomAttributes(typeof(Bind), true);
            if (bind.Length > 0)
                return ((Bind)bind[0]).Name;
            else
                return property.Name;
        }

        /// <summary>
        /// 获取实体有效的属性数组,特定类型,排除不需要绑定的属性
        /// </summary>
        /// <param name="classType"></param>
        /// <returns></returns>
        private static PropertyInfo[] GetProperties(Type classType)
        {

            //允许的数据类型
            string[] typeList = new string[]{
                typeof(int).Name,
                typeof(string).Name,
                typeof(DateTime).Name,
                typeof(bool).Name,
                typeof(Guid).Name,
                typeof(byte).Name
            };

            return classType.GetProperties().Where(m => typeList.Contains(m.PropertyType.Name)).ToArray();

        }

        /// <summary>
        /// 把实体属性生成键值对(只取有效的实体属性)
        /// </summary>
        private static Dictionary<string, object> GetPropertyKeyValue(object entity)
        {
            Dictionary<string, object> list = new Dictionary<string, object>();

            var proList = GetProperties(entity.GetType());

            foreach (PropertyInfo item in proList)
            {
                var name = GetBindName(item);
                list.Add(name.ToLower(), item.GetValue(entity, null));
            }
            return list;
        }

        /// <summary>
        /// 根据sql语句和实体属性键值对生成参数数组
        /// </summary>
        private static SqlParameter[] GetCommandParameters(string sql, Dictionary<string, object> parames)
        {
            List<SqlParameter> p = new List<SqlParameter>();
            string[] strArr = sql.Split(new char[] { ',', '=', ')', '(', ' ', '%', '\r' });
            //查找
            foreach (string s in strArr)
            {
                if (s.StartsWith("@"))
                {
                    //已经赋值的不重复
                    if (p.Exists(m => m.ParameterName == s.ToLower()))
                        continue;

                    string key = s.Replace("@", "").ToLower();
                    if (parames.ContainsKey(key))
                        p.Add(new SqlParameter(s, parames[key] ?? DBNull.Value));
                    //else
                    //    throw new ArgumentException("实体属性中没有找到与数据库对应的字段", key);
                }
            }
            if (p.Count == 0)
                return null;
            return p.ToArray();
        }

        /// <summary>
        /// 根据带参数形式的sql语句和实体 生成参数数组
        /// </summary>
        public static SqlParameter[] GetSqlParameters(string sql, object entity)
        {
            return GetCommandParameters(sql, GetPropertyKeyValue(entity));
        }
        #endregion

        #region 把数据库对象转换成实体

        /// <summary>
        /// 通过反射绑定一个实体,默认绑定规则: 属性名=字段名  | 特殊规则:自定义特性Bind("name")=字段名
        /// </summary>
        public static T BindEntity<T>(SqlDataReader dr) where T : new()
        {
            if (dr.Read())
            {
                T entity = new T();

                foreach (PropertyInfo item in GetProperties(entity.GetType()))
                {
                    Type type = item.PropertyType;
                    string name = GetBindName(item);

                    //如果DataRow列名包含此属性
                    if (dr[name] != null)
                    {
                        //赋值
                        object value = Convert.ChangeType(dr[name], type);
                        item.SetValue(entity, value, null);
                    }
                }
                return entity;
            }
            else
                return default(T);
        }

        /// <summary>
        /// 通过反射绑定一个实体,默认绑定规则: 属性名=字段名  | 特殊规则:自定义特性Bind("name")=字段名
        /// </summary>
        public static T BindEntity<T>(DataTable tb) where T : new()
        {
            if (tb.Rows.Count == 0) return default(T);
            return BindEntity<T>(tb.Rows[0]);
        }


        /// <summary>
        /// 通过反射绑定一个实体,默认绑定规则: 属性名=字段名  | 特殊规则:自定义特性Bind("name")=字段名
        /// </summary>
        public static T BindEntity<T>(DataRow row) where T : new()
        {
            if (row == null) return default(T);
            T entity = new T();
            foreach (PropertyInfo item in GetProperties(entity.GetType()))
            {
                Type type = item.PropertyType;
                string name = GetBindName(item);

                //如果DataRow列名包含此属性
                if (row[name] != null)
                {
                    //赋值
                    object value = Convert.ChangeType(row[name], type);
                    item.SetValue(entity, value, null);
                }
            }
            return entity;
        }

        /// <summary>
        /// 把一张表绑定成实体列表
        /// </summary>
        public static List<T> BindEntityList<T>(DataTable tb) where T : new()
        {
            if (tb.Rows.Count == 0)
                return default(List<T>);
            List<T> list = new List<T>();
            foreach (DataRow dr in tb.Rows)
            {
                list.Add(BindEntity<T>(dr));
            }
            return list;
        }

        #endregion

        #region CRUD操作

        /// <summary>
        /// 向数据库插入数据,实体必须声明 Tab特性
        /// </summary>
        public static int Insert(object entity)
        {
            var tab = GetTabAttribute(entity);
            var proList = GetPropertyKeyValue(entity);

            //删除自增主键列
            if (tab.AutoPrimarykey)
                proList.Remove(tab.Primarykey.ToLower());

            string key = string.Join(",", proList.Select(m => "[" + m.Key + "]"));
            string val = string.Join(",", proList.Select(m => "@" + m.Key));

            string sql = string.Format("insert into [{0}] ({1}) values ({2}) ", tab.TabName, key, val);

            var p = GetCommandParameters(sql, proList);
            return CR.SqlHelper.ExecuteNonQuery(CommandType.Text, sql, p);
        }

        /// <summary>
        /// 修改实体,实体必须声明 Tab特性
        /// </summary>
        public static int Update(object entity)
        {
            var tab = GetTabAttribute(entity);
            var proList = GetPropertyKeyValue(entity);

            //生成set部分,不生成主键列
            string set = string.Join(",", proList.Where(m => m.Key != tab.Primarykey.ToLower()).Select(m => string.Format("[{0}]=@{0}", m.Key)));

            string sql = string.Format("update [{0}] set {1} where [{2}]=@{2}", tab.TabName, set, tab.Primarykey);
            var p = GetCommandParameters(sql, proList);
            return CR.SqlHelper.ExecuteNonQuery(CommandType.Text, sql, p);
        }

        /// <summary>
        /// 通过主键删除一个实体对应的数据,实体必须声明 Tab特性
        /// </summary>
        public static int Delete<T>(object key) where T : new()
        {
            var tab = GetTabAttribute<T>();
            var sql = string.Format("delete  from [{0}] where [{1}]=@{1}", tab.TabName, tab.Primarykey);
            var p = new SqlParameter("@" + tab.Primarykey, key);
            return CR.SqlHelper.ExecuteNonQuery(CommandType.Text, sql, new SqlParameter[] { p });
        }

        /// <summary>
        /// 通过主键获取一个实体 ,实体必须声明 Tab特性
        /// </summary>
        public static T Get<T>(object key) where T : new()
        {
            var tab = GetTabAttribute<T>();
            string sql = string.Format("select top 1 *  from [{0}] where [{1}]=@{1} ", tab.TabName, tab.Primarykey);
            SqlParameter[] parames = new SqlParameter[1];
            parames[0] = new SqlParameter("@" + tab.Primarykey, key);
            return Get<T>(sql, parames);
        }

        /// <summary>
        /// 通过自定义sql语句获取一个实体 ,实体必须声明 Tab特性
        /// </summary>
        public static T Get<T>(string sql) where T : new()
        {
            return Get<T>(CommandType.Text, sql, null);
        }
        /// <summary>
        /// 通过自定义sql语句获取一个实体 ,实体必须声明 Tab特性
        /// </summary>
        public static T Get<T>(string sql, SqlParameter[] parames) where T : new()
        {
            return Get<T>(CommandType.Text, sql, parames);
        }
        /// <summary>
        /// 通过自定义sql语句获取一个实体 ,实体必须声明 Tab特性
        /// </summary>
        public static T Get<T>(CommandType type, string sql, SqlParameter[] parames) where T : new()
        {
            using (DataTable tb = CR.SqlHelper.ExecuteDataTable(type, sql, parames))
            {
                return BindEntity<T>(tb);
            }
        }

        /// <summary>
        /// 获取所有数据,为了性能,最多1000条
        /// </summary>
        public static List<T> GetList<T>() where T : new()
        {
            var tab = GetTabAttribute(new T());
            var sql = string.Format("select top 1000 *  from [{0}]", tab.TabName);
            return GetList<T>(CommandType.Text, sql, null);
        }

        /// <summary>
        /// 根据sql语句获取实体列表
        /// </summary>
        public static List<T> GetList<T>(string sql) where T : new()
        {
            return GetList<T>(CommandType.Text, sql, null);
        }
        /// <summary>
        /// 根据sql语句和参数获取实体列表
        /// </summary>
        public static List<T> GetList<T>(string sql, SqlParameter[] parames) where T : new()
        {
            return GetList<T>(CommandType.Text, sql, parames);
        }
        /// <summary>
        /// 根据sql语句获取实体列表,可以通过CommandType来指定使用存储过程
        /// </summary>
        public static List<T> GetList<T>(CommandType type, string sql, SqlParameter[] parames) where T : new()
        {
            using (DataTable tb = SqlHelper.ExecuteDataTable(type, sql, parames))
            {
                return BindEntityList<T>(tb);
            }
        }

        #endregion

    }
}

 

ailin 写于2011年国庆

 

本类的功能分3个方面:

1.定义实体的特性(如对应的表名 主键名 属性对应的列名)

2.实体和数据库对象的相互转换

3.简单实体的 CRUD操作

 

全部代码 :  (引用了一个SqlHelper数据库操作辅助类)

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值