菜鸟用c 实现一轻量级的mysql_轻量级ORM框架Dapper应用八:使用Dapper实现DTO

一、什么是DTO

先来看看百度百科的解释:

数据传输对象(DTO)(Data Transfer Object),是一种设计模式之间传输数据的软件应用系统。数据传输目标往往是数据访问对象从数据库中检索数据。数据传输对象与数据交互对象或数据访问对象之间的差异是一个以不具有任何行为除了存储和检索的数据(访问和存取器)。

二、为什么需要DTO

在一个软件系统的实现中,我们常常需要访问数据库,并将从数据库中所取得的数据显示在用户界面上。这样做的一个问题是:用于在用户界面上展示的数据模型和从数据库中取得的数据模型常常具有较大区别。在这种情况下,我们常常需要向服务端发送多个请求才能将用于在页面中展示的数据凑齐。

三、使用Dapper实现DTO

使用Dapper可以直接返回DTO类型,包括两种方式:

新建Category、ProductDetail和ProductDTO实体类:

Category实体类定义如下:

1 usingSystem;2 usingSystem.Collections.Generic;3 usingSystem.Linq;4 usingSystem.Text;5 usingSystem.Threading.Tasks;6

7 namespaceDapperConvertDto8 {9 public classCategory10 {11 public int CategoryId { get; set; }12 public string CategoryName { get; set; }13 }14 }

ProductDetail实体类定义如下:

1 usingSystem;2 usingSystem.Collections.Generic;3 usingSystem.Linq;4 usingSystem.Text;5 usingSystem.Threading.Tasks;6

7 namespaceDapperConvertDto8 {9 public classProductDetail10 {11 public int ProductId { get; set; }12

13 public string ProductName { get; set; }14

15 public double Price { get; set; }16

17 public int CategoryId { get; set; }18 }19 }

ProductDTO实体类定义如下:

1 usingSystem;2 usingSystem.Collections.Generic;3 usingSystem.Linq;4 usingSystem.Text;5 usingSystem.Threading.Tasks;6

7 namespaceDapperConvertDto8 {9 public classProductDto10 {11 public int ProductId { get; set; }12

13 public string ProductName { get; set; }14

15 public double ProductPrice { get; set; }16

17 public string CategoryName { get; set; }18 }19 }

ProductDTO实体类中的ProductPrice对应ProductDetail表的Price,CategoryName对应Category表的CategoryName。

方式一:直接在SQL语句中使用as

1 usingSystem;2 usingSystem.Collections.Generic;3 usingSystem.Data.SqlClient;4 usingSystem.Linq;5 usingSystem.Text;6 usingSystem.Threading.Tasks;7 usingDapper;8

9 namespaceDapperConvertDto10 {11 classProgram12 {13 static void Main(string[] args)14 {15 //数据库连接

16 string strCon = @"Initial Catalog=StudentSystem; Integrated Security=False;User Id=sa;Password=1qaz@WSX;Data Source=127.0.0.1;Failover Partner=127.0.0.1;Application Name=TransForCCT";17 SqlConnection conn = newSqlConnection(strCon);18

19 //方式一:直接在SQL语句中使用as,将查询的字段转换成DTO类型的属性

20 string strSql = @"SELECT p.ProductId,p.ProductName,p.Price AS ProductPrice,c.CategoryName FROM Category c INNER JOIN ProductDetail p ON c.CategoryId=p.CategoryId";21 ProductDto product = conn.Query(strSql).FirstOrDefault();22 }23 }24 }

结果:

0a336d9e6a67fadbc765f66dd23229e0.png

从截图中看出,返回的就是想要的DTO类型。

方式二:使用委托的方式进行映射,分别把Category和ProductDetail实体类里的属性,映射成ProductDTO类型的属性:

1 usingSystem;2 usingSystem.Collections.Generic;3 usingSystem.Data.SqlClient;4 usingSystem.Linq;5 usingSystem.Text;6 usingSystem.Threading.Tasks;7 usingDapper;8

9 namespaceDapperConvertDto10 {11 classProgram12 {13 static void Main(string[] args)14 {15 //数据库连接

16 string strCon = @"Initial Catalog=StudentSystem; Integrated Security=False;User Id=sa;Password=1qaz@WSX;Data Source=127.0.0.1;Failover Partner=127.0.0.1;Application Name=TransForCCT";17 SqlConnection conn = newSqlConnection(strCon);18

19 //方式一:直接在SQL语句中使用as,将查询的字段转换成DTO类型的属性

20 string strSql = @"SELECT p.ProductId,p.ProductName,p.Price AS ProductPrice,c.CategoryName FROM Category c INNER JOIN ProductDetail p ON c.CategoryId=p.CategoryId";21 ProductDto product = conn.Query(strSql).FirstOrDefault();22

23 //方式二:使用委托进行自定义映射

24 string strSql2 = @"SELECT p.ProductId,p.ProductName,p.Price,c.CategoryName FROM Category c INNER JOIN ProductDetail p ON c.CategoryId=p.CategoryId";25 //定义映射的委托

26 Func map = (p, c) =>

27 {28 ProductDto dto = newProductDto();29 dto.ProductId =p.ProductId;30 dto.ProductName =p.ProductName;31 dto.ProductPrice =p.Price;32 dto.CategoryName =c.CategoryName;33 returndto;34 };35 //splitOn表示查询的SQL语句中根据哪个字段进行分割

36 string splitOn = "CategoryName";37 List list = conn.Query(strSql2, map, splitOn: splitOn).ToList();38 }39 }40 }

结果:

136f65ee6fee131b175451e2b689fdad.png

注意:

1、splitOn

splitOn表示查询的SQL语句中按照哪个字段进行分割,splitOn的顺序是从右向左的,遇到splitOn设置的字段接结束,把从右边开始到设置的这个字段归为同一个实体。例如:上面的例子中,splitOn设置为CategoryName,则表示从右边开始,到CategoryName为止的所有字段都是属于Category这个实体的,剩余的字段都是属于ProductDetail实体的。

2、注意委托中实体类的前后顺序

委托中实体类的前后顺序一定要和查询的SQL语句中字段的前后顺序一致,上面的例子中先查询的ProductDetail、后查询的Category,那么定义委托的时候,要先写ProductDetail,后写Category,如果委托中实体类的顺序错了,那么不会得到映射的数据,看下面的例子:

1 usingSystem;2 usingSystem.Collections.Generic;3 usingSystem.Data.SqlClient;4 usingSystem.Linq;5 usingSystem.Text;6 usingSystem.Threading.Tasks;7 usingDapper;8

9 namespaceDapperConvertDto10 {11 classProgram12 {13 static void Main(string[] args)14 {15 //数据库连接

16 string strCon = @"Initial Catalog=StudentSystem; Integrated Security=False;User Id=sa;Password=1qaz@WSX;Data Source=127.0.0.1;Failover Partner=127.0.0.1;Application Name=TransForCCT";17 SqlConnection conn = newSqlConnection(strCon);18

19 //方式一:直接在SQL语句中使用as,将查询的字段转换成DTO类型的属性

20 string strSql = @"SELECT p.ProductId,p.ProductName,p.Price AS ProductPrice,c.CategoryName FROM Category c INNER JOIN ProductDetail p ON c.CategoryId=p.CategoryId";21 ProductDto product = conn.Query(strSql).FirstOrDefault();22

23 //方式二:使用委托进行自定义映射

24 string strSql2 = @"SELECT p.ProductId,p.ProductName,p.Price,c.CategoryName FROM Category c INNER JOIN ProductDetail p ON c.CategoryId=p.CategoryId";25 //定义映射的委托26 //Func map = (p, c) =>27 //{28 //ProductDto dto = new ProductDto();29 //dto.ProductId = p.ProductId;30 //dto.ProductName = p.ProductName;31 //dto.ProductPrice = p.Price;32 //dto.CategoryName = c.CategoryName;33 //return dto;34 //};35

36 //错误的委托

37 Func map = (c,p) =>

38 {39 ProductDto dto = newProductDto();40 dto.ProductId =p.ProductId;41 dto.ProductName =p.ProductName;42 dto.ProductPrice =p.Price;43 dto.CategoryName =c.CategoryName;44 returndto;45 };46

47 //splitOn表示查询的SQL语句中根据哪个字段进行分割

48 string splitOn = "CategoryName";49 List list = conn.Query< Category, ProductDetail, ProductDto>(strSql2, map, splitOn: splitOn).ToList();50 }51 }52 }

结果:

6d89c5977c2c43ef0d1cddd33be09959.png

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值