减少重复工作,通过泛型反射写一个通用的Ado.net操作数据库的简单orm底层

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了减少重复工作,通过泛型反射写一个通用的Ado.net操作数据库的简单orm底层相关的知识,希望对你有一定的参考价值。

 创建一个基类BaseEntity:

 public class BaseEntity
    {
        [PrimaryKey]
        public int Id { get; set; }
        public DateTime CreateTime { get; set; }
        public Status Status { get; set; }
        public string Remark { get; set; }
    }

    /// <summary>
    /// 自增主键标识
    /// </summary>
    public class PrimaryKey : Attribute
    {

    }

  然后创建一个泛型底层类,这里用的数据库是mysql,如果是其它数据库,需要注意相应的关键字,比如sqlserver中user表在写sql时需要写成“[user]”。

/// <summary>
    /// 已实现增删改查的底层基类 T类的属性需要和表字段保持一致
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BaseAccessory<T> where T : BaseEntity, new()
    {
        protected DBHelper dBHelper = new DBHelper();
        private Type Type;
        private PropertyInfo[] Props;
        private PropertyInfo KeyProp;//主键属性

        /// <summary>
        /// 构造函数
        /// </summary>
        public BaseAccessory()
        {
            Type = typeof(T);
            //下一步 将类型对应的属性写入缓存
            Props = Type.GetProperties();
            KeyProp = Props.First(f => f.CustomAttributes.Count(d => d.AttributeType == typeof(PrimaryKey)) > 0);
        }

        /// <summary>
        /// 根据主键获取实体数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public T GetModel(int keyValue)
        {
            var sql = $"select {string.Join(",", Props.Select(f => f.Name))} from {Type.Name} where {KeyProp.Name} = {keyValue}";
            var cmd = dBHelper.GetSqlStringCommond(sql);
            using (var reader = dBHelper.ExecuteReader(cmd))
            {
                while (reader.Read())
                {
                    var t = new T();
                    foreach (var prop in Props)
                    {
                        prop.SetValue(t, reader[prop.Name]);
                    }
                    return t;
                }
            }
            return null;
        }

        /// <summary>
        /// 更新实体
        /// </summary>
        /// <param name="model"></param>
        /// <returns>受影响的行数</returns>
        public int Update(T model, Trans t = null)
        {
            var sql = $"UPDATE {Type.Name} SET {string.Join(",", Props.Select(f => f.Name + "=‘" + f.GetObjValue(model) + "‘"))} where {KeyProp.Name}={KeyProp.GetValue(model)} ";
            var cmd = dBHelper.GetSqlStringCommond(sql);
            if (t is null) { return dBHelper.ExecuteNonQuery(cmd); }
            else { return dBHelper.ExecuteNonQuery(cmd, t); }
        }

        /// <summary>
        /// 写入实体
        /// </summary>
        /// <param name="model"></param>
        /// <returns>受影响的行数</returns>
        public int Insert(T model, Trans t = null)
        {
            var sql = [email protected]"INSERT INTO {Type.Name} ({string.Join(",", Props.Where(f => f.Name != KeyProp.Name).Select(f => f.Name))}) VALUES({string.Join(",", Props.Where(f => f.Name != KeyProp.Name).Select(f => "‘" + f.GetObjValue(model) + "‘"))}); select @@IDENTITY";
            var cmd = dBHelper.GetSqlStringCommond(sql);
            object id;
            if (t is null) { id = dBHelper.ExecuteScalar(cmd); }
            else { id = dBHelper.ExecuteScalar(cmd, t); }
            return Convert.ToInt32(id);
        }

        public int Delete(int keyValue, Trans t = null)
        {
            var sql = $"delete  {Type.Name} where {KeyProp.Name} = {keyValue}";
            var cmd = dBHelper.GetSqlStringCommond(sql);
            if (t is null) { return dBHelper.ExecuteNonQuery(cmd); }
            else { return dBHelper.ExecuteNonQuery(cmd, t); }
        }

    }

  最后在业务代码中就可以调用该类:

 /// <summary>
    /// 用户表实体类 属性需要和表字段保持一致
    /// </summary>
    public class User : BaseEntity
    {
        public string LoginName { get; set; }
        public string Password { get; set; }
        public string RealName { get; set; }
        public string PhoneNumber { get; set; }
    }

public class UserAccessory : BaseAccessory<User>
    {

    }

public class Main{
        public void TestMethod1()
        {
            UserAccessory userDal = new UserAccessory();
            var user = userDal.GetModel(2);
            user.LoginName = "哈哈泛型的强大,更新成功";
            userDal.Update(user);
            user.LoginName = "哈哈泛型的强大,写入成功";
            var id = userDal.Insert(user);
        }
}

  

以上是关于减少重复工作,通过泛型反射写一个通用的Ado.net操作数据库的简单orm底层的主要内容,如果未能解决你的问题,请参考以下文章

通用持久层如何设计

用泛型和反射实现函数通用

基于表单数据的封装,泛型,反射以及使用BeanUtils进行处理

实现一个通用的中英文排序工具

Java反射的理解-- 通过反射了解集合泛型的本质

在.NET中使用反射调用泛型方法[重复]