一、什么是DTO

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

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

二、为什么需要DTO

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

三、使用Dapper实现DTO

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

新建Category、ProductDetail和ProductDTO实体类:

Category实体类定义如下:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace DapperConvertDto
{
public class Category
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
}
}

ProductDetail实体类定义如下:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace DapperConvertDto
{
public class ProductDetail
{
public int ProductId { get; set; } public string ProductName { get; set; } public double Price { get; set; } public int CategoryId { get; set; }
}
}

ProductDTO实体类定义如下:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace DapperConvertDto
{
public class ProductDto
{
public int ProductId { get; set; } public string ProductName { get; set; } public double ProductPrice { get; set; } public string CategoryName { get; set; }
}
}

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

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

 using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper; namespace DapperConvertDto
{
class Program
{
static void Main(string[] args)
{
// 数据库连接
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";
SqlConnection conn = new SqlConnection(strCon); // 方式一:直接在SQL语句中使用as,将查询的字段转换成DTO类型的属性
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 ";
ProductDto product = conn.Query<ProductDto>(strSql).FirstOrDefault<ProductDto>();
}
}
}

结果:

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

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

 using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper; namespace DapperConvertDto
{
class Program
{
static void Main(string[] args)
{
// 数据库连接
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";
SqlConnection conn = new SqlConnection(strCon); // 方式一:直接在SQL语句中使用as,将查询的字段转换成DTO类型的属性
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 ";
ProductDto product = conn.Query<ProductDto>(strSql).FirstOrDefault<ProductDto>(); // 方式二:使用委托进行自定义映射
string strSql2 = @" SELECT p.ProductId,p.ProductName,p.Price,c.CategoryName FROM Category c INNER JOIN ProductDetail p ON c.CategoryId=p.CategoryId ";
// 定义映射的委托
Func<ProductDetail, Category, ProductDto> map = (p, c) =>
{
ProductDto dto = new ProductDto();
dto.ProductId = p.ProductId;
dto.ProductName = p.ProductName;
dto.ProductPrice = p.Price;
dto.CategoryName = c.CategoryName;
return dto;
};
// splitOn表示查询的SQL语句中根据哪个字段进行分割
string splitOn = "CategoryName";
List<ProductDto> list = conn.Query<ProductDetail, Category, ProductDto>(strSql2, map, splitOn: splitOn).ToList<ProductDto>();
}
}
}

结果:

注意:

1、splitOn

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

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

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

 using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper; namespace DapperConvertDto
{
class Program
{
static void Main(string[] args)
{
// 数据库连接
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";
SqlConnection conn = new SqlConnection(strCon); // 方式一:直接在SQL语句中使用as,将查询的字段转换成DTO类型的属性
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 ";
ProductDto product = conn.Query<ProductDto>(strSql).FirstOrDefault<ProductDto>(); // 方式二:使用委托进行自定义映射
string strSql2 = @" SELECT p.ProductId,p.ProductName,p.Price,c.CategoryName FROM Category c INNER JOIN ProductDetail p ON c.CategoryId=p.CategoryId ";
// 定义映射的委托
//Func<ProductDetail, Category, ProductDto> map = (p, c) =>
//{
// ProductDto dto = new ProductDto();
// dto.ProductId = p.ProductId;
// dto.ProductName = p.ProductName;
// dto.ProductPrice = p.Price;
// dto.CategoryName = c.CategoryName;
// return dto;
//}; // 错误的委托
Func<Category, ProductDetail, ProductDto> map = (c,p) =>
{
ProductDto dto = new ProductDto();
dto.ProductId = p.ProductId;
dto.ProductName = p.ProductName;
dto.ProductPrice = p.Price;
dto.CategoryName = c.CategoryName;
return dto;
}; // splitOn表示查询的SQL语句中根据哪个字段进行分割
string splitOn = "CategoryName";
List<ProductDto> list = conn.Query< Category, ProductDetail, ProductDto>(strSql2, map, splitOn: splitOn).ToList<ProductDto>();
}
}
}

结果:

轻量级ORM框架Dapper应用八:使用Dapper实现DTO的更多相关文章

  1. 轻量级ORM框架初探-Dapper与PetaPoco的基本使用

    一.EntityFramework EF是传统的ORM框架,也是一个比较重量级的ORM框架.这里仍然使用EF的原因在于为了突出轻量级ORM框架的性能,所谓有对比才有更优的选择. 1.1 准备一张数据库 ...

  2. .NET轻量级ORM框架Dapper入门精通

    一.课程介绍 本次分享课程包含两个部分<.NET轻量级ORM框架Dapper修炼手册>和<.NET轻量级ORM框架Dapper葵花宝典>,阿笨将带领大家一起领略轻量级ORM框架 ...

  3. 轻量级ORM框架Dapper应用一:Dapper安装

    一.Dapper简介 Dapper是一款轻量级ORM框架,为解决网站访问流量极高而产生的性能问题而构造,主要通过执行TSQL表达式而实现数据库的CQRS. 如果你在项目中遇到性能访问问题,选择Dapp ...

  4. 分享自己写的基于Dapper的轻量级ORM框架~

    1.说明 本项目是一个使用.NET Standard 2.0开发的,基于 Dapper 的轻量级 ORM 框架,包含基本的CRUD以及根据表达式进行一些操作的方法,目前只针对单表,不包含多表连接操作. ...

  5. C# 性能优化 之 秒表 Stopwatch。 Dapper一个和petapoco差不多的轻量级ORM框架

    Sweet小马 小马同学的编程日记. C# 性能优化 之 秒表 Stopwatch. 生词解释:Diagnostics[,daɪəg'nɑstɪks] n.诊断学 using System.Diagn ...

  6. c# 轻量级ORM框架 实现(一)

    发布一个自己写的一个轻量级ORM框架,本框架设计期初基于三层架构.所以从命名上来看,了解三层的朋友会很好理解. 设计该框架的目的:不想重复的写增删改查,把精力放到功能实现上. 发布改框架的原因:希望给 ...

  7. 轻量级ORM框架 QX_Frame.Bantina(二、框架使用方式介绍)

    轻量级ORM框架QX_Frame.Bantina系列讲解(开源) 一.框架简介 http://www.cnblogs.com/qixiaoyizhan/p/7417467.html 二.框架使用方式介 ...

  8. 轻量级ORM框架 QX_Frame.Bantina(一、框架简介)

    轻量级ORM框架QX_Frame.Bantina系列讲解(开源) 一.框架简介 http://www.cnblogs.com/qixiaoyizhan/p/7417467.html 二.框架使用方式介 ...

  9. 轻量级ORM框架——第一篇:Dapper快速学习

    我们都知道ORM全称叫做Object Relationship Mapper,也就是可以用object来map我们的db,而且市面上的orm框架有很多,其中有一个框架 叫做dapper,而且被称为th ...

  10. 基于轻量级ORM框架Dapper的扩展说明

    这里简单的介绍一下本人基于Dapper作的一些简单的扩展,供大家参考. 为何要使用这款框架,相信大家看到下面排名就清楚了 其实在各大网站上,我们大概都会看到这样的一个对比效果图,在超过500次poco ...

随机推荐

  1. 转 kafka 清理数据

    由于项目原因,最近经常碰到Kafka消息队列拥堵的情况.碰到这种情况为了不影响在线系统的正常使用,需要大家手动的清理Kafka Log.但是清理Kafka Log又不能单纯的去删除中间环节产生的日志, ...

  2. java项目中显示图表:struts2整合jfreechart

    需要的包: struts2-jfreechart-plugin-2.2.1.1.jar jfreechart-1.0.13.jar jcommon-1.0.17.jar 前台jsp页面中可以使用ifr ...

  3. js刷新小知识点

    data.code == '200' ? window.location.reload() : alert('拷贝失败,请重试') #如果状态码是200就刷新页面,如果不是就提示拷贝失败,请重试 页面 ...

  4. Entity Framework 同一个上下文中,如何进行对同一个实体进行指定字段更新

    转自 http://www.cnblogs.com/flyfish2012/archive/2013/03/13/2957125.html 我在上一篇EF更新指定的字段当中介绍了,如何在EF指定字段进 ...

  5. Oozie工作流属性配置的方式与策略

    本文原文出处: http://blog.csdn.net/bluishglc/article/details/46049817 Oozie工作流属性配置的三种方式 Oozie有三种方法可以给工作流提供 ...

  6. 关于iReport-5.6.0之前版本 “无法启动”或者“一开就关闭”的 某些原因

    在经过Google搜索后.外国的大神说: We don't support Java 8 right now. Support will be added in next versions. 大概意思 ...

  7. 批处理向FTP上传指定属性的文件 批处理增量备份的例子

    使用windows批处理向FTP上传具有指定属性的文件,类似增量备份功能. 对一个目录里的几个文件自动上传FTP时只上传有归档属性的文件,然后FTP上传成功后自动清除(本机)刚上传文件的归档属性. 类 ...

  8. Atitit 遍历文件夹算法 autoit attilax总结

    Atitit 遍历文件夹算法 autoit attilax总结 _FileListToArray Lists files and\or folders in a specified folder (S ...

  9. 修改PS1变量

    PS1='\[\e[7;46m\]\u\[\e[0m\]@\[\e[0;32m\]\h\[\e[0m\]:\[\e[0;34m\]\w\[\e[0m\]\$ ' from: http://profes ...

  10. Python使用读写excel文件

    Python使用openpyxl读写excel文件 这是一个第三方库,可以处理xlsx格式的Excel文件.pip install openpyxl安装.如果使用Aanconda,应该自带了. 读取E ...