博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
轻量级ORM框架Dapper应用八:使用Dapper实现DTO
阅读量:5962 次
发布时间:2019-06-19

本文共 7126 字,大约阅读时间需要 23 分钟。

一、什么是DTO

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

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

二、为什么需要DTO

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

三、使用Dapper实现DTO

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

新建Category、ProductDetail和ProductDTO实体类:

Category实体类定义如下:

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6  7 namespace DapperConvertDto 8 { 9     public class Category10     {11         public int CategoryId { get; set; }12         public string CategoryName { get; set; }13     }14 }

ProductDetail实体类定义如下:

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6  7 namespace DapperConvertDto 8 { 9     public class ProductDetail10     {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 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6  7 namespace DapperConvertDto 8 { 9     public class ProductDto10     {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 using System; 2 using System.Collections.Generic; 3 using System.Data.SqlClient; 4 using System.Linq; 5 using System.Text; 6 using System.Threading.Tasks; 7 using Dapper; 8  9 namespace DapperConvertDto10 {11     class Program12     {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 = new SqlConnection(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 }

 

结果:

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

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

1 using System; 2 using System.Collections.Generic; 3 using System.Data.SqlClient; 4 using System.Linq; 5 using System.Text; 6 using System.Threading.Tasks; 7 using Dapper; 8  9 namespace DapperConvertDto10 {11     class Program12     {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 = new SqlConnection(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 // splitOn表示查询的SQL语句中根据哪个字段进行分割36 string splitOn = "CategoryName";37 List
list = conn.Query
(strSql2, map, splitOn: splitOn).ToList
();38 }39 }40 }

 

结果:

 

注意:

1、splitOn

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

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

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

1 using System; 2 using System.Collections.Generic; 3 using System.Data.SqlClient; 4 using System.Linq; 5 using System.Text; 6 using System.Threading.Tasks; 7 using Dapper; 8  9 namespace DapperConvertDto10 {11     class Program12     {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 = new SqlConnection(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 = new ProductDto();40 dto.ProductId = p.ProductId;41 dto.ProductName = p.ProductName;42 dto.ProductPrice = p.Price;43 dto.CategoryName = c.CategoryName;44 return dto;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 }

 结果:

 

转载地址:http://jbjax.baihongyu.com/

你可能感兴趣的文章
关于self.用法的一些总结
查看>>
代码上线的十二个步骤
查看>>
Office Visio简介
查看>>
TensorFlow学习_NN
查看>>
Java方式 MySQL数据库连接
查看>>
TPYBoard MicroPython 固件开发教程使用mpy-cross工具生成mpy文件
查看>>
android微信分享不出去?四步搞定!
查看>>
SpringCloud之Eureka入门使用
查看>>
C# 泛型约束 xxx Where T:约束(二)
查看>>
如何解决web大流量,高并发问题
查看>>
phpmyadmin内存溢出
查看>>
StrutsTestCase测试Struts应用程序
查看>>
使用ArcGIS Engine开发ArcGIS Server的胖客户端浏览程序
查看>>
在VirtualBox下安装CentOS教程(截图版)
查看>>
centos 7 安装JDK (Linux安装jdk)
查看>>
被忽视的Compaction策略-有关NoSQL Compaction策略的一点思考
查看>>
【UR #7】水题走四方 题解
查看>>
[转摘] 关于C#中委托和事件机制的一个最佳实例
查看>>
数据库复习
查看>>
unix 环境高级编程
查看>>