任逍遥

 找回密码
 立即注册
查看: 30655|回复: 100

AutoMapper6.x起步

    [复制链接]
  • TA的每日心情

    2020-9-5 20:20
  • 签到天数: 487 天

    连续签到: 1 天

    [LV.9]妙领天机

    530

    主题

    3431

    帖子

    4572

    积分

    如雷贯耳

    Rank: 8Rank: 8

    积分
    4572
    发表于 2018-7-23 21:36:55 | 显示全部楼层 |阅读模式

    马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x

      写在前面
      这段时间写自己的博客系统,遇到的问题还是不少的,其中有部分就是要通过EntityFramework调用存储过程,而EF生成的存储过程会单独地生成一个存储过程的实体类,要从这个存储过程的实体类转换到普通的实体类这就麻烦了,得不停地去反射操作,当然有些时候还得在视图模型和实体之间转换(OOM),这都只有通过反射来操作,太麻烦!要是实体中有集合属性或者导航属性,那就更麻烦了!AutoMapper就自动帮我们解决了这样的问题,所以,将自己的学习成果记在这里,方便自己以后忘记时再次查阅,也方便初学者起步:
      OOM顾名思义,Object-Object-Mapping实体间相互转换,AutoMapper也是个老生常谈了,其意义在于帮助你无需手动的转换简单而又麻烦的实体间关系,比如ViewModel和entity的转换,SearchModel和Entity的转换,关于automapper的使用,网上大多数的分享都是几年前的,很多方法已经被废弃,到了编译器里会告诉你该方法已经过时,废弃的,不建议使用的,比如Mapper.CreateMap等方法,当然老司机大多数直接就去github看文档了,或者google一下就了解了,但是中文资料关于方法废弃后,并没有什么说明了,对于小白那就可能就痛苦了。本篇的五个实例可以帮你解决常见的基本问题.
      预备
      首先我们预备一些DTO和TModel。DTO就是你和用户交互的实体,专业解释为数据传输对象(Data Transfer Object),你也可以理解为视图模型(ViewModel)。TModel就是你与数据库打交道的实体。
      实体展示如下:
      TModel有如下三个简单的实体,他们有独立的实体,也有一对多的实体。
      public class Address
      {
      public string Country { get; set; }
      public string City { get; set; }
      public string Street { get; set; }
      public string PostCode { get; set; }
      public string CreateTime { get; set; }
      public int CreateUserId { get; set; }
      }
      public class Author
      {
      public string Name { get; set; }
      public string Description { get; set; }
      public List<Contact> Contact { get; set; }
      }
      public class Contact
      {
      public int Id { get; set; }
      public string Email { get; set; }
      public string Blog { get; set; }
      public string Twitter { get; set; }
      }
      DTO对象有如下三个:
      public class AddressDto
      {
      public string Country { get; set; }
      public string City { get; set; }
      public string City2 { get; set; }
      }
      public class AuthorDto
      {
      public string Name { get; set; }
      public string Description { get; set; }
      public List<ContactDto> Contact { get; set; }
      }
      public class ContactDto
      {
      public int Id { get; set; }
      public string Email { get; set; }
      public string Blog { get; set; }
      public string Twitter { get; set; }
      }
      起步:单个实体转换
      单个实体转换的时候,在属性字段名称完全匹配的情况下,你只需指定两个实体间的转换规则,指定source源实体和destination目标实体。那么你应该参照如下实例:
      var dto= new AddressDto
      {
      Country = "China",
      City = "Beijing"
      };
      Mapper.Initialize(m => m.CreateMap<AddressDto, Address>());
      Address address = Mapper.Map<AddressDto, Address>(dto);
      请注意在AutoMapper5.x当中,Initialize来初始化你的规则是首选的。
      在你指定转换规则后,请使用Map方法,进行转换并输出你的目标实体。还有第一个参数代表SourceModel,第二个参数是DestinationModel.
      单个实体不同名属性转换
      当你需要对不同名称的字段来进行映射的时候,请注意使用ForMember方法,第一个参数需要你制定所需特殊配置的目标字段,第二个参数你则需要制定你对该字段属性的操作,我选择了它提供的MapFrom方法,意义在于告诉AutoMapper,我需要讲目标实体的City来源 指定为 源实体的City2属性值。
      var dto = new AddressDto
      {
      Country = "China",
      City2 = "Beijing"
      };
      Mapper.Initialize(m => m.CreateMap<AddressDto, Address>().ForMember(x => x.City, opt => opt.MapFrom(o => o.City2)));
      Address address = Mapper.Map<AddressDto, Address>(dto);
      集合转换
      在集合间转换的时候,你不需要配置目标List与源List对象中的匹配,而只需要配置你泛型对象的映射匹配关系。
      var address = new Address { Country = "China", City = "Beijing" };
      var address2 = new Address() { Country = "USA", City = "New York" };
      var addressList = new List<Address>() { address2, address };
      Mapper.Initialize(m => m.CreateMap<Address, AddressDto>());//这里仅需配置实体间的转换,而不是实体集合的转换
      List<AddressDto> res = Mapper.Map<List<Address>, List<AddressDto>>(addressList);
      实体包含不同类型属性转换(忽略属性)
      在实体包含不同类型属性的时候,比如TModel1中包含了一个List<TModel>,而你的Dto1中包含了一个List<Dto>.这个时候你可以选择忽略这个属性
      var contacts = new List<Contact>() { new Contact(){ Blog = "myblog", Email = "[email protected]" }, new Contact() { Blog = "myblog", Email = "[email protected]" } };
      var author = new Author() { Description = "描述", Name = "李四", Contact = contacts };
      Mapper.Initialize(m => { m.CreateMap<Author, AuthorDto>().ForMember(x => x.Contact, opt => opt.Ignore()); });
      AuthorDto Dto = Mapper.Map<Author, AuthorDto>(author);
      //这里的Ignore代表配置Contract该属性的操作  为忽略Ignore,映射时将忽略该属性,由于List<Contact>()和List<ContactDto>() 是不同类型,所以需要配置忽略或者是特殊映射,特殊映射例子看下方
      实体包含不同类型属性转换(指定属性Mapfrom)
      当然你需要这个属性的时候,你可以不忽略他,而是使用MapFrom来进行特殊的指定,并且在类型不相同的时候,你要指定你两个类型间的映射匹配关系。正如下面实例中的m.CreateMap<Contact, ContactDto>(); 和 m.CreateMap<Author, AuthorDto>().ForMember(x => x.Contact, opt => opt.MapFrom(o => o.Contact));
      var contacts = new List<Contact>()
      {
      new Contact() {Blog = "myblog", Email = "[email protected]"},
      new Contact() {Blog = "myblog", Email = "[email protected]"}
      };
      var author = new Author() {Description = "描述", Name = "张三", Contact = contacts};
      Mapper.Initialize(m =>
      {
      m.CreateMap<Contact, ContactDto>(); //注意内部不同类型实体转换时必要的
      m.CreateMap<Author, AuthorDto>().ForMember(x => x.Contact, opt => opt.MapFrom(o => o.Contact)); //注意制定MapFrom是必要的
      });
    楼主热帖
  • TA的每日心情
    难过
    2019-8-30 07:50
  • 签到天数: 490 天

    连续签到: 1 天

    [LV.9]妙领天机

    5

    主题

    2943

    帖子

    2946

    积分

    声名显赫

    Rank: 7Rank: 7Rank: 7

    积分
    2946
    发表于 2018-7-23 21:42:56 | 显示全部楼层
    佩服佩服!
    回复

    使用道具 举报

  • TA的每日心情
    擦汗
    2019-8-29 01:01
  • 签到天数: 475 天

    连续签到: 3 天

    [LV.9]妙领天机

    0

    主题

    2941

    帖子

    2937

    积分

    声名显赫

    Rank: 7Rank: 7Rank: 7

    积分
    2937
    发表于 2018-7-26 13:54:24 | 显示全部楼层
    我也是坐沙发的
    回复

    使用道具 举报

  • TA的每日心情

    2019-8-29 12:52
  • 签到天数: 471 天

    连续签到: 5 天

    [LV.9]妙领天机

    12

    主题

    2971

    帖子

    2978

    积分

    声名显赫

    Rank: 7Rank: 7Rank: 7

    积分
    2978
    发表于 2018-7-27 19:09:48 | 显示全部楼层
    顶起顶起顶起
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2019-8-30 20:48
  • 签到天数: 484 天

    连续签到: 4 天

    [LV.9]妙领天机

    3

    主题

    2891

    帖子

    2888

    积分

    声名显赫

    Rank: 7Rank: 7Rank: 7

    积分
    2888
    发表于 2018-7-28 13:14:02 | 显示全部楼层
    路过 帮顶 嘿嘿
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2019-8-30 11:06
  • 签到天数: 472 天

    连续签到: 1 天

    [LV.9]妙领天机

    2

    主题

    2944

    帖子

    2944

    积分

    声名显赫

    Rank: 7Rank: 7Rank: 7

    积分
    2944
    发表于 2018-7-30 11:18:30 | 显示全部楼层
    我也来顶一下..
    回复

    使用道具 举报

  • TA的每日心情

    2019-8-30 19:36
  • 签到天数: 464 天

    连续签到: 8 天

    [LV.9]妙领天机

    1

    主题

    2862

    帖子

    2858

    积分

    声名显赫

    Rank: 7Rank: 7Rank: 7

    积分
    2858
    发表于 2018-7-30 15:02:56 | 显示全部楼层
    支持你哈...................................
    回复

    使用道具 举报

  • TA的每日心情
    擦汗
    2019-8-30 19:53
  • 签到天数: 464 天

    连续签到: 5 天

    [LV.9]妙领天机

    1

    主题

    2910

    帖子

    2909

    积分

    声名显赫

    Rank: 7Rank: 7Rank: 7

    积分
    2909
    发表于 2018-7-31 17:07:29 | 显示全部楼层
    路过 帮顶 嘿嘿
    回复

    使用道具 举报

  • TA的每日心情

    2019-8-29 08:52
  • 签到天数: 470 天

    连续签到: 4 天

    [LV.9]妙领天机

    1

    主题

    2945

    帖子

    2944

    积分

    声名显赫

    Rank: 7Rank: 7Rank: 7

    积分
    2944
    发表于 2018-8-1 00:43:57 | 显示全部楼层
    不错 支持一个了
    回复

    使用道具 举报

  • TA的每日心情

    2019-8-30 17:53
  • 签到天数: 471 天

    连续签到: 5 天

    [LV.9]妙领天机

    0

    主题

    2848

    帖子

    2843

    积分

    声名显赫

    Rank: 7Rank: 7Rank: 7

    积分
    2843
    发表于 2018-8-1 16:29:50 | 显示全部楼层
    这么强,支持楼主,佩服
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|小黑屋|任逍遥

    GMT+8, 2024-5-5 23:48 , Processed in 0.078117 second(s), 49 queries .

    Powered by 任逍遥 X3.4

    Copyright © 2001-2023, Rxiaoyao Cloud.

    快速回复 返回顶部 返回列表