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() == ;
//新增后把id拿出来? 可以的,在sql后面增加个 Select @@Identity; ExecuteScalar
}
}

用反射、泛型 改造SqlHelper的更多相关文章

  1. Java学习笔记之使用反射+泛型构建通用DAO

    PS:最近简单的学了学后台Servlet+JSP.也就只能学到这里了.没那么多精力去学SSH了,毕竟Android还有很多东西都没学完.. 学习内容: 1.如何使用反射+泛型构建通用DAO. 1.使用 ...

  2. 【C# 反射泛型】

    C# 反射泛型 摘自:http://www.itwis.com/html/net/c/20110411/10175.html C#泛型反射和普通反射的区别,泛型反射和普通反射的区别就是泛型参数的处理上 ...

  3. Javaweb学习笔记——(二十七)——————泛型、泛型的通配符、反射泛型信息、反射注解、注解

    泛型     1.泛型类:具有一个或多个类型变量的类,称之为泛型类 class A<T>{ } 2.在创建泛型实例时,需要为其类型变量赋值 A<String> a = new ...

  4. 【译】9. Java反射——泛型

    原文地址:http://tutorials.jenkov.com/java-reflection/generics.html ===================================== ...

  5. JAVA常用基础知识点[继承,抽象,接口,静态,枚举,反射,泛型,多线程...]

    类的继承 Java只支持单继承,不允许多重继承- 一个子类只能有一个父类- 一个父类可以派生出多个子类这里写图片描述子类继承了父类,就继承了父类的方法和属性.在子类中,可以使用父类中定义的方法和属性, ...

  6. C#中反射泛型 CreateInstance

    假设1我有个类叫SortClass,类中有个BubbleSort(int[] array)用于给数组进行排序. 假设2我有个类叫SortT<T>,类中有个BubbleSort(T[] ar ...

  7. DataReader反射泛型对象

    昨天听同学说,要把DataReader对象转成实体对象,要写一个通用的方法.想了下用反射应该可以做到.项目中一般都是用第三方组件来做数据访问层,如,Nhibernate.ef等.于是自己想写个简单例子 ...

  8. C#反射の反射泛型

    C#反射の反射详解(点击跳转)C#反射の反射接口(点击跳转)C#反射反射泛型接口(点击跳转)C#反射の一个泛型反射实现的网络请求框架(点击跳转) 接上篇. 自定义一个泛型类(继承于接口) public ...

  9. Java下的框架编程(反射,泛型,元数据,CGLib,代码动态生成,AOP,动态语言嵌入)

    Java 虽然没有动态语言般暴起,但仍然天连天,水接水的生出好多框架技术---反射(reflection),泛型(generics),元数据(annotation),proxies(proxy/cgl ...

随机推荐

  1. 「newbee-mall新蜂商城开源啦」1000 Star Get !仓库Star数破千!记录一下

    新蜂商城已经开源了 3 个多月左右的时间,在 2019 年的年末,仓库的 Star 数量冲破了 1000,整理本篇文章的时间是 2020 年 1 月 12 日,目前的 Star 数量是 1180 左右 ...

  2. vue中动态设置echarts画布大小

    document.getElementById('news-shopPagechart').style.height = this.heightpx2+'px'; //heightpx2定义在data ...

  3. Spring中常见的设计模式——适配器模式

    一.适配器模式的应用场景 适配器模式(Adapter Pattern)是指将一个类的接口转换成用户期待的另一个接口,使原本接口不兼容的类可以一起工作,属于构造设计模式. 适配器适用于以下几种业务场景: ...

  4. Broken Necklace 坏掉的项链 USACO 模拟(易错)

    1004: 1.1.4Broken Necklace 坏掉的项链 时间限制: 1 Sec  内存限制: 128 MB提交: 11  解决: 9[提交] [状态] [讨论版] [命题人:外部导入] 题目 ...

  5. scratch3.0二次开发scratch3.0基本介绍(第一章)

    为什么要自己开发而不使用官方版本? 这个问题要看我们的做少儿编程教育的需求是怎么样的. scratch本身提供了离线版本以及官网在线平台供我们使用,这足以满足我们对于编程教学模块的需求.但是对于一些教 ...

  6. java 数组2

    一.创建异常 1.空指针异常 2.超出索引范围 二.遍历 for循环 三.求数组中的最大值 package cn.wt.day05.demon02; public class DemonArray03 ...

  7. url的分发

    一.分发 补充:通过查看源码:可以通过二级路由include进行二次分发 位置:urls.py urlpatterns = [ path('admin/', admin.site.urls), pat ...

  8. [mvc>actionResult] 封装一个操作方法的结果并用于代表该操作方法执行框架级操作

  9. 看看AQS阻塞队列和条件队列

    上一篇简单介绍了AQS,我们大概知道AQS就是一个框架,把很多功能都给实现了(比如入队规则,唤醒节点中的线程等),我们如果要使用的话只需要实现其中的一些方法(比如tryAcquire等)就行了!这次主 ...

  10. PTA 练习 7-24 喊山 (30 分)

    7-24 喊山 (30 分) 喊山,是人双手围在嘴边成喇叭状,对着远方高山发出"喂-喂喂-喂喂喂--"的呼唤.呼唤声通过空气的传递,回荡于深谷之间,传送到人们耳中,发出约定俗成的& ...