用反射、泛型 改造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 } }
付费内容,请联系本人QQ:1002453261
本文来自博客园,作者:明志德道,转载请注明原文链接:https://www.cnblogs.com/for-easy-fast/articles/12312175.html