十年河东,十年河西,莫欺少年穷。

学无止境,精益求精。

不扯犊子,直接进入正题:

AutoMapper自动映射常用于EF中,能很好的解决DTO和Model之间相互映射的问题。在未使用AutoMapper之前,我们回顾下传统的对象相互映射的方法。

首先贴出本节要用到的DTO,学生表及系表,他们之间存在主外键关系!如下:

    public partial class Dept
{
public Dept()
{
this.Student = new HashSet<Student>();
} public int Id { get; set; }
public string deptNum { get; set; }
public string deptName { get; set; } public virtual ICollection<Student> Student { get; set; }
} public partial class Student
{
public int Id { get; set; }
public string StuNum { get; set; }
public string deptNum { get; set; }
public string StuName { get; set; }
public string StuSex { get; set; }
public Nullable<System.DateTime> AddTime { get; set; } public virtual Dept Dept { get; set; }
}

假设,现在要求将得到的学生对象转化为Model

新建学生对象Model

    public class StudentModel
{
public int Id { get; set; }
public string StuNum { get; set; }
public string deptNum { get; set; }
public string StuName { get; set; }
public string StuSex { get; set; }
public Nullable<System.DateTime> AddTime { get; set; }
}

传统方法如下:

        public ActionResult Index()
{
var profiler = MiniProfiler.Current; using (profiler.Step("查询Student的数据"))
{
using (BingFaTestEntities context = new BingFaTestEntities())
{
var SM = context.Student.Where(A => A.StuNum == "").FirstOrDefault();
if (SM != null)
{
var StudetM = new StudentModel()
{
Id = SM.Id,
StuName = SM.StuNum,
StuNum = SM.StuNum,
StuSex = SM.StuSex,
deptNum = SM.deptNum,
AddTime = SM.AddTime
};
}
}
return View();
}
}

传统方法实现相互映射存在一个弊端,如果数据表字段特别多,那么,试问你需要写多少行代码?

OK,AutoMapper闪亮登场,那么如果使用AutoMapper需要写什么样的代码呢?

        public ActionResult Index()
{
var profiler = MiniProfiler.Current; using (profiler.Step("查询Student的数据"))
{
using (BingFaTestEntities context = new BingFaTestEntities())
{
var SM = context.Student.Where(A => A.StuNum == "").FirstOrDefault();
if (SM != null)
{
StudentModel StudentM = Mapper.DynamicMap<StudentModel>(SM);
}
}
return View();
}
}

由上述代码可知,其相互映射只需一行代码搞定。这里需要注意,你定义的Model层个字段属性要和DTO层字段属性一致。

OK,那如果需要转化一个泛型集合呢?

传统方法如下:

        public ActionResult Index()
{
var profiler = MiniProfiler.Current; using (profiler.Step("查询Student的数据"))
{
using (BingFaTestEntities context = new BingFaTestEntities())
{
var SMList = context.Student.Where(A => A.StuName.Contains("陈")).ToList();
if (SMList != null&&SMList.Count>)
{
foreach (var SM in SMList)
{
var StudetM = new StudentModel()
{
Id = SM.Id,
StuName = SM.StuNum,
StuNum = SM.StuNum,
StuSex = SM.StuSex,
deptNum = SM.deptNum,
AddTime = SM.AddTime
};
}
}
}
return View();
}
}

那么,AutoMapper是否可以做到呢?

当然,可以...

        public ActionResult Index()
{
var profiler = MiniProfiler.Current; using (profiler.Step("查询Student的数据"))
{
using (BingFaTestEntities context = new BingFaTestEntities())
{
var SMList = context.Student.Where(A => A.StuName.Contains("陈")).ToList();
if (SMList != null && SMList.Count > )
{
List<StudentModel> StudentM = Mapper.DynamicMap<List<StudentModel>>(SMList);
}
}
return View();
}
}

有上述代码可知,是不是连Foreach都省了?

哈哈,OK,这些都是些基础功能,咱们继续深究。

如果需要映射导航属性对应表中的字段怎么写呢?

我们将StudentModel修改成如下:

如果要得到系名称 deptName ,我们就要用到EF的懒加载。关于用EF懒加载时要注意的事项,大家可参考博客: EF性能优化-有人说EF性能低,我想说:EF确实不如ADO.NET,当然本节也会详细说明。

首先用传统方法实现如下:

        public ActionResult Index()
{
var profiler = MiniProfiler.Current; using (profiler.Step("查询Student的数据"))
{
using (BingFaTestEntities context = new BingFaTestEntities())
{
var SM = context.Student.Where(A => A.StuNum == "").FirstOrDefault();
if (SM != null)
{
var StudetM = new StudentModel()
{
Id = SM.Id,
StuName = SM.StuNum,
StuNum = SM.StuNum,
StuSex = SM.StuSex,
deptNum = SM.deptNum,
AddTime = SM.AddTime,
deptName=SM.Dept.deptName
};
}
}
return View();
}
}

传统方法变化不大,那么,用AutoMapper怎么实现呢?

        public ActionResult Index()
{
var profiler = MiniProfiler.Current; using (profiler.Step("查询Student的数据"))
{
using (BingFaTestEntities context = new BingFaTestEntities())
{
var SM = context.Student.Where(A => A.StuNum == "").FirstOrDefault();
AutoMapper.Mapper.CreateMap<Student, StudentModel>().ForMember(dest => dest.deptName, opts => opts.MapFrom(src => src.Dept.deptName));
var model = AutoMapper.Mapper.Map<StudentModel>(SM);
}
return View();
}
}

由上述方法可知,使用AutoMapper方法进行映射,需要指定目标字段dest.deptName 以及 源字段 src.Dept.deptName,关于AutoMapper的详细用法及说明大家可参考:【来龙去脉系列】AutoMapper一款自动映射框架

在这里,我要告诫大家关于使用懒加载的注意事项,如果你不注意,那么你写的代码效率有可能将会非常低。

如上述两种方法,我们来监控下生成的SQL语句:(关于是如果监控生成的SQL语句,大家可参考我的博客:MiniProfiler工具介绍(监控EF生成的SQL语句)--EF,迷你监控器,哈哈哈

生成了2条SQL语句:

OK,仅仅生成两条SQL语句还可以接受,但是如果你的项目数据表关系比较复杂,有很多导航属性时,就会生成很多SQL语句,会产生极大的性能问题。

那么关于懒加载的问题怎么解决呢?还好,EF中有Include,在使用Include时需要引入using System.Data.Entity;

将上边的程序修改成如下:

        public ActionResult Index()
{
var profiler = MiniProfiler.Current; using (profiler.Step("查询Student的数据"))
{
using (BingFaTestEntities context = new BingFaTestEntities())
{
var SMList = context.Student.Include(A=>A.Dept).Where(A => A.StuName.Contains("陈")).ToList();
AutoMapper.Mapper.CreateMap<Student, StudentModel>()
.ForMember(dest => dest.deptName, opts => opts.MapFrom(src => src.Dept.deptName));
var modelList = AutoMapper.Mapper.Map<List<StudentModel>>(SMList);
}
return View();
}
}

使用Include,其实相当于声明弃用懒加载,这里使用显示加载!

OK,关于使用AutoMapper应用懒加载的方法讲完了。正如上述所说:AutoMapper是将DTO映射成Model,如果反过来映射是否可行呢?

还好,AutoMapper提供了.ReverseMap();方法,将Model映射成DTO,如下:

        public ActionResult Index()
{
var profiler = MiniProfiler.Current; using (profiler.Step("查询Student的数据"))
{
using (BingFaTestEntities context = new BingFaTestEntities())
{
StudentModel M = new StudentModel()
{
StuName = "陈星辰",
AddTime = DateTime.Now,
deptNum = "",
StuNum = "",
StuSex = "男"
};
Student Sm = new Student();
AutoMapper.Mapper.CreateMap<StudentModel, Student>().ReverseMap();
Sm = AutoMapper.Mapper.Map<Student>(M);
context.Student.Add(Sm);
context.SaveChanges();
}
return View();
}
}

OK。截止到这里,关于AutoMapper的基础用法也就讲完了,本人能力有限,如有未提及之处,请大家多多指点。希望大家喜欢!

@陈卧龙的博客

最新文章

  1. CSS3新增的选择器和属性
  2. SQL获取汉字首字母
  3. C#中去除字符串空格的三种方法
  4. Angular 2 要来了,Wijmo 已准备好迎接
  5. poj2533 LIS
  6. Intellij IDEA 快捷键(Mac)
  7. 蓝牙Bluetooth技术手册规范下载
  8. [原创]java WEB学习笔记85:Hibernate学习之路-- -映射 一对一关系 ,基于主键方式实现
  9. 山东理工大学第七届ACM校赛-最大收益问题 分类: 比赛 2015-06-26 10:25 51人阅读 评论(0) 收藏
  10. zlib用法说明
  11. Webform——内嵌word编辑器
  12. FCKEditor的用法与下载
  13. VMware连不上网解决
  14. Thread interrupt方法解析
  15. HDU 4569Special equations2012长沙邀请赛E题(数学知识)
  16. 1.1.7-学习Opencv与MFC混合编程之---为画图工具添加工具栏
  17. java短路问题
  18. 使用live555 在linux下搭建 rtsp server
  19. Generative Adversarial Nets[Introduction]
  20. PLSQL 错误问题:Datebase character set (AL32UTF-8) and Client character set (ZHS16GBK) are different.

热门文章

  1. MySQL&#160;InnoDB表和索引之聚簇索引与第二索引
  2. loadrunner&#160;运行场景-场景运行原理
  3. Video.js web视频播放器
  4. [20171107]dbms_shared_pool.pin补充.txt
  5. 大表分批删除脚本之MySQL版
  6. 【18】如何把数据存储到MongoDB数据库
  7. Spring容器技术内幕之内部工作机制
  8. python第四十五课——继承性之多继承
  9. [NOI2005]瑰丽华尔兹
  10. 键值对的算子讲解 PairRDDFunctions