用反射、泛型 改造SqlHelper

1.  数据准备

    public class BaseModel
    {
        public int Id { set; get; }
    }

    public class Company : BaseModel
    {
        public string Name { get; set; }
        public System.DateTime CreateTime { get; set; }
        public int CreatorId { get; set; }
        /// <summary>
        /// Eleven 
        /// int?可空字段 既可以是int  也可以是null
        /// 数据库设计的时候  字段是可空null
        /// </summary>
        public int? LastModifierId { get; set; }//Nullable<int>
        public DateTime? LastModifyTime { get; set; }
    }

    public class User : BaseModel
    {
        public string Name { get; set; }
        public string Account { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
        public string Mobile { get; set; }
        public int? CompanyId { get; set; }
        public string CompanyName { get; set; }
        public int State { get; set; }
        public int UserType { get; set; }
        public DateTime? LastLoginTime { get; set; }
        public DateTime CreateTime { get; set; }
        public int CreatorId { get; set; }
        public int? LastModifierId { get; set; }

    }

2. 写通用接口方法

    public interface IBaseDAL
    {
        T FindT<T>(int id) where T : BaseModel;
        List<T> FindAll<T>() where T : BaseModel;
        bool Add<T>(T t) where T : BaseModel;
        bool Update<T>(T t) where T : BaseModel;
        bool Delete<T>(T t) where T : BaseModel;
    }

3. 用泛型、反射 实现接口中的方法

        public T FindT<T>(int id) where T : BaseModel
        {
            Type type = typeof(T);
            string sql = $"SELECT {string.Join(",", type.GetProperties().Select(p => $"[{p.Name}]"))} FROM [{type.Name}] WHERE ID={id}";
            using (SqlConnection conn = new SqlConnection(ConnectionStringCustomers))
            {
                SqlCommand command = new SqlCommand(sql, conn);
                conn.Open();
                var reader = command.ExecuteReader();
                if (reader.Read())
                {
                    return this.Trans<T>(type, reader);
                }
                else
                {
                    return null;//Eleven  数据库没有,应该返回null  而不是一个默认对象
                }
            }
        }


        private T Trans<T>(Type type, SqlDataReader reader)
        {
            object oObject = Activator.CreateInstance(type);
            foreach (var prop in type.GetProperties())
            {
                //prop.SetValue(oObject, reader[prop.Name]]);
                //Eleven 可空类型,如果数据库存储的是null,直接SetValue会报错的
                prop.SetValue(oObject, reader[prop.Name] is DBNull ? null : reader[prop.Name]);
            }
            
        public List<T> FindAll<T>() where T : BaseModel
        {
            Type type = typeof(T);
            string sql = $"SELECT {string.Join(",", type.GetProperties().Select(p => $"[{p.Name}]"))} FROM [{type.Name}]";
         
            //你的类名称如果跟命名空间重复了,也不能用
            //string sql = ElevenSqlBuilder<T>.FindAllSql;
            using (SqlConnection conn = new SqlConnection(ConnectionStringCustomers))
            {
                SqlCommand command = new SqlCommand(sql, conn);
                conn.Open();
                var reader = command.ExecuteReader();
                List<T> tList = new List<T>();
                //object oObject = Activator.CreateInstance(type);
                while (reader.Read())
                {


                    tList.Add(this.Trans<T>(type, reader));
                }
                return tList;
            }
        }
        public bool Add<T>(T t) where T : BaseModel
        {
            
            //id是自增的  所以不能新增

            Type type = t.GetType();

            string columnString = string.Join(",", type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public)//不要父类的
                                                                                                                                              //.Where(p=>!p.Name.Equals("Id"))//去掉id--主键约束了
                .Select(p => $"[{p.Name}]"));
            //string valueColumn = string.Join(",", type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public).Select(p => $"'{p.GetValue(t)}'"));
            //引号怎么加---sqlserver 任意值都可以加单引号
            //假如都加引号,如果Name的值里面有个单引号,sql变成什么样的  Eleven's  sql会错
            //还有sql注入风险
            //所以要参数化
            string valueColumn = string.Join(",", type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public)
                .Select(p => $"@{p.Name}"));
            var parameterList = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public)
                .Select(p => new SqlParameter($"@{p.Name}", p.GetValue(t) ?? DBNull.Value));//注意可空类型

            string sql = $"Insert [{type.Name}] ({columnString}) values({valueColumn})";
            using (SqlConnection conn = new SqlConnection(ConnectionStringCustomers))
            {
                SqlCommand command = new SqlCommand(sql, conn);
                command.Parameters.AddRange(parameterList.ToArray());
                conn.Open();
                return command.ExecuteNonQuery() == 1;
                //新增后把id拿出来?  可以的,在sql后面增加个 Select @@Identity; ExecuteScalar
            }
        }

 

posted @ 2020-02-15 15:03  明志德道  阅读(406)  评论(0编辑  收藏  举报