千家信息网

ASP.NET Core如何使用AutoMapper实现实体映射

发表于:2024-11-12 作者:千家信息网编辑
千家信息网最后更新 2024年11月12日,这篇文章将为大家详细讲解有关ASP.NET Core如何使用AutoMapper实现实体映射,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、前言在实际的项目开发过
千家信息网最后更新 2024年11月12日ASP.NET Core如何使用AutoMapper实现实体映射

这篇文章将为大家详细讲解有关ASP.NET Core如何使用AutoMapper实现实体映射,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

一、前言

在实际的项目开发过程中,我们使用各种ORM框架可以使我们快捷的获取到数据,并且可以将获取到的数据绑定到对应的List中,然后页面或者接口直接显示List中的数据。但是我们最终想要显示在视图或者接口中的数据和数据库实体之间可能存在着差异,一般的做法就是去创建一些对应的"模型"类,然后对获取到的数据再次进行处理,从而满足需求。

因此,如果便捷的实现数据库持久化对象与模型对象之间的实体映射,避免在去代码中手工实现这一过程,就可以大大降低开发的工作量。AutoMapper就是可以帮助我们实现实体转换过程的工具。

二、使用AutoMapper实现实体映射

AutoMapper是一个OOM(Object-Object-Mapping)组件,从它的英文名字中可以看出,AutoMapper主要是为了实现实体间的相互转换,从而避免我们每次采用手工的方式进行转换。在没有OOM这类组件之前,如果我们需要实现实体之间的转换,只能使用手工修改代码,然后逐个赋值的方式实现映射,而有了OOM组件,可以很方便的帮助我们实现这一需求。看下面的一个例子。

首先创建一个ASP.NET Core WebApi项目:

添加一个Student实体类:

namespace AutoMapperDemo.Model{    public class Student    {        public int ID { get; set; }        public string Name { get; set; }        public int Age { get; set; }        public string Gender { get; set; }    }}

添加StudentDTO类,跟Student属性一致。

然后添加一个类,模拟一些测试数据:

using AutoMapperDemo.Model;using System.Collections.Generic;namespace AutoMapperDemo{    public class Data    {        public static List ListStudent { get; set; }        public static List GetList()        {            ListStudent = new List();            for (int i = 0; i < 3; i++)            {                Student student = new Student()                 {                  ID=i,                  Name=$"测试_{i}",                  Age=20,                  Gender="男"                };                ListStudent.Add(student);            }            return ListStudent;        }    }}

添加Student控制器,通过Get方法获取所有的值:

using System.Collections.Generic;using System.Threading.Tasks;using AutoMapperDemo.Model;using Microsoft.AspNetCore.Mvc;namespace AutoMapperDemo.Controllers{    [Route("api/[controller]")]    [ApiController]    public class StudentController : ControllerBase    {        [HttpGet]        public async Task> Get()        {            List list = new List();            list = await Task.Run>(() =>             {                return Data.GetList();            });            return list;        }    }}

使用Postman进行测试:

这样返回的数据直接就是数据库对应的实体类类型。这时需求改变了,我们要返回StudentDTO类型的数据,这时就需要修改代码:

using System.Collections.Generic;using System.Threading.Tasks;using AutoMapperDemo.DTO;using AutoMapperDemo.Model;using Microsoft.AspNetCore.Mvc;namespace AutoMapperDemo.Controllers{    [Route("api/[controller]")]    [ApiController]    public class StudentController : ControllerBase    {        [HttpGet]        public async Task> Get()        {            List list = new List();            list = await Task.Run>(() =>             {                return Data.GetList();            });            return list;        }        [HttpGet("GetDTO")]        public async Task> GetDto()        {            List list = new List();            List  listStudent = await Task.Run>(() =>            {                return Data.GetList();            });            // 循环给属性赋值            foreach (var item in listStudent)            {                StudentDTO dto = new StudentDTO();                dto.ID = item.ID;                dto.Name = item.Name;                dto.Age = item.Age;                dto.Gender = item.Gender;                // 加入到集合中                list.Add(dto);            }            return list;        }    }}

还是使用Postman进行测试:

可以看到:这时返回的是DTO类型的数据。这种情况就是我们上面说的,需要手动修改代码,然后循环给对应的属性进行赋值。这里Student类只有4个属性,如果属性非常多,或者很多地方使用到了,如果还是采用这种方式进行赋值,那么就会很麻烦。假如以后其中的一个属性名称改变了,那么所有的地方也都需要修改,工作量就会很大。这时就需要使用AutoMapper解决。

首先引入AutoMapper包,直接在NuGet中引入:

这里选择安装AutoMapper.Extensions.Microsoft.DependencyInjection这个包。这个包主要是为了让我们可以通过依赖注入的方式去使用AutoMapper。

新建StudentProfile类,继承自AutoMapper的Profile类,在无参构造函数中,我们就可以通过 CreateMap 方法去创建两个实体间的映射关系。

using AutoMapper;using AutoMapperDemo.DTO;using AutoMapperDemo.Model;namespace AutoMapperDemo.AutoMapper{    ///     /// 继承自Profile类    ///     public class StudentProfile: Profile    {        ///         /// 构造函数中实现映射        ///         public StudentProfile()        {            // Mapping            // 第一次参数是源类型(这里是Model类型),第二个参数是目标类型(这里是DTO类型)            CreateMap();        }    }}

这里的 Profile有什么用呢?services.AddAutoMapper他会自动找到所有继承了Profile的类然后进行配置。

然后修改Student控制器,通过构造函数使用AutoMapper的注入,并使用AutoMapper实现自动映射:

using System.Collections.Generic;using System.Threading.Tasks;using AutoMapper;using AutoMapperDemo.DTO;using AutoMapperDemo.Model;using Microsoft.AspNetCore.Mvc;namespace AutoMapperDemo.Controllers{    [Route("api/[controller]")]    [ApiController]    public class StudentController : ControllerBase    {        private readonly IMapper _mapper;        ///         /// 通过构造函数实现依赖注入        ///         ///         public StudentController(IMapper mapper)        {            _mapper = mapper;        }        [HttpGet]        public async Task> Get()        {            List list = new List();            list = await Task.Run>(() =>             {                return Data.GetList();            });            return list;        }        [HttpGet("GetDTO")]        public async Task> GetDto()        {            List list = new List();            List  listStudent = await Task.Run>(() =>            {                return Data.GetList();            });            //// 循环给属性赋值            //foreach (var item in listStudent)            //{            //    StudentDTO dto = new StudentDTO();            //    dto.ID = item.ID;            //    dto.Name = item.Name;            //    dto.Age = item.Age;            //    dto.Gender = item.Gender;            //    // 加入到集合中            //    list.Add(dto);            //}            // 使用AutoMapper进行映射            list = _mapper.Map>(listStudent);            return list;        }    }}

修改Startup类的ConfigureServices方法,添加AutoMapper:

public void ConfigureServices(IServiceCollection services){    #region 使用AutoMapper    // 参数类型是Assembly类型的数组 表示AutoMapper将在这些程序集数组里面遍历寻找所有继承了Profile类的配置文件    // 在当前作用域的所有程序集里面扫描AutoMapper的配置文件    services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());    #endregion    services.AddControllers();}

再次使用Postman进行测试:

可以看到,这样也实现了我们的需求,而且还不需要进行手动映射。

上面的示例中,Student和StudentDTO类里面的属性名称都是一样的,如果属性名称不一样呢?我们把StudentDTO类里面的ID改为StudentID,然后修改映射代码:

using AutoMapper;using AutoMapperDemo.DTO;using AutoMapperDemo.Model;namespace AutoMapperDemo.AutoMapper{    ///     /// 继承自Profile类    ///     public class StudentProfile: Profile    {        ///         /// 构造函数中实现映射        ///         public StudentProfile()        {            // Mapping            // 第一次参数是源类型(这里是Model类型),第二个参数是目标类型(这里是DTO类型)            // CreateMap();            // 使用自定义映射 Student类的ID映射到StudentDTO类的StudentID            CreateMap()                .ForMember(destinationMember: des => des.StudentID, memberOptions: opt => { opt.MapFrom(mapExpression: map => map.ID); });        }    }}

再次使用Postman进行测试:

这样就实现了自定义映射。这里是映射了一个字段,如果是多个字段不同呢? 修改StudentDTO类:

namespace AutoMapperDemo.DTO{    public class StudentDTO    {        public int StudentID { get; set; }        public string StudentName { get; set; }        public int StudentAge { get; set; }        public string StudentGender { get; set; }    }}

然后修改映射配置类:

using AutoMapper;using AutoMapperDemo.DTO;using AutoMapperDemo.Model;namespace AutoMapperDemo.AutoMapper{    ///     /// 继承自Profile类    ///     public class StudentProfile: Profile    {        ///         /// 构造函数中实现映射        ///         public StudentProfile()        {            // Mapping            // 第一次参数是源类型(这里是Model类型),第二个参数是目标类型(这里是DTO类型)            // CreateMap();            // 使用自定义映射 Student类的ID映射到StudentDTO类的StudentID            //CreateMap()            //    .ForMember(destinationMember: des => des.StudentID, memberOptions: opt => { opt.MapFrom(mapExpression: map => map.ID); });            // 对多个属性进行自定义映射            CreateMap()                .ForMember(destinationMember: des => des.StudentID, memberOptions: opt => { opt.MapFrom(mapExpression: map => map.ID); })                .ForMember(destinationMember: des => des.StudentName, memberOptions: opt => { opt.MapFrom(mapExpression: map => map.Name); })                .ForMember(destinationMember: des => des.StudentAge, memberOptions: opt => { opt.MapFrom(mapExpression: map => map.Age); })                .ForMember(destinationMember: des => des.StudentGender, memberOptions: opt => { opt.MapFrom(mapExpression: map => map.Gender); });        }    }}

在使用Postman进行测试:

这样就实现了多个属性的自定义映射。

上面的实例中是从Student映射到StudentDTO,那么可以从StudentDTO映射到Student吗?答案是肯定的,只需要在映射的最后使用ReverseMap()方法即可:

using AutoMapper;using AutoMapperDemo.DTO;using AutoMapperDemo.Model;namespace AutoMapperDemo.AutoMapper{    ///     /// 继承自Profile类    ///     public class StudentProfile: Profile    {        ///         /// 构造函数中实现映射        ///         public StudentProfile()        {            // Mapping            // 第一次参数是源类型(这里是Model类型),第二个参数是目标类型(这里是DTO类型)            // CreateMap();            // 使用自定义映射 Student类的ID映射到StudentDTO类的StudentID            //CreateMap()            //    .ForMember(destinationMember: des => des.StudentID, memberOptions: opt => { opt.MapFrom(mapExpression: map => map.ID); });            // 对多个属性进行自定义映射            CreateMap()                .ForMember(destinationMember: des => des.StudentID, memberOptions: opt => { opt.MapFrom(mapExpression: map => map.ID); })                .ForMember(destinationMember: des => des.StudentName, memberOptions: opt => { opt.MapFrom(mapExpression: map => map.Name); })                .ForMember(destinationMember: des => des.StudentAge, memberOptions: opt => { opt.MapFrom(mapExpression: map => map.Age); })                .ForMember(destinationMember: des => des.StudentGender, memberOptions: opt => { opt.MapFrom(mapExpression: map => map.Gender); })                // ReverseMap表示双向映射                .ReverseMap();        }    }}

我们修改Data,里面增加一个Add方法,可以将Student添加到集合中:

using AutoMapperDemo.Model;using System.Collections.Generic;namespace AutoMapperDemo{    public class Data    {        public static List ListStudent { get; set; }        static Data()        {            ListStudent = new List();            for (int i = 0; i < 3; i++)            {                Student student = new Student()                {                    ID = i,                    Name = $"测试_{i}",                    Age = 20,                    Gender = "男"                };                ListStudent.Add(student);            }        }        public static List GetList()        {            return ListStudent;        }        public static void Add(Student entity)        {            ListStudent.Add(entity);        }    }}

修改Student控制器,添加一个Post方法,传入的参数的StudentDTO类型:

using System.Collections.Generic;using System.Threading.Tasks;using AutoMapper;using AutoMapperDemo.DTO;using AutoMapperDemo.Model;using Microsoft.AspNetCore.Mvc;namespace AutoMapperDemo.Controllers{    [Route("api/[controller]")]    [ApiController]    public class StudentController : ControllerBase    {        private readonly IMapper _mapper;        ///         /// 通过构造函数实现依赖注入        ///         ///         public StudentController(IMapper mapper)        {            _mapper = mapper;        }        [HttpGet]        public async Task> Get()        {            List list = new List();            list = await Task.Run>(() =>             {                return Data.GetList();            });            return list;        }        [HttpGet("GetDTO")]        public async Task> GetDto()        {            List list = new List();            List  listStudent = await Task.Run>(() =>            {                return Data.GetList();            });            //// 循环给属性赋值            //foreach (var item in listStudent)            //{            //    StudentDTO dto = new StudentDTO();            //    dto.ID = item.ID;            //    dto.Name = item.Name;            //    dto.Age = item.Age;            //    dto.Gender = item.Gender;            //    // 加入到集合中            //    list.Add(dto);            //}            // 使用AutoMapper进行映射            list = _mapper.Map>(listStudent);            return list;        }        [HttpPost]        public async Task> Post([FromBody]StudentDTO entity)        {            List list = new List();            // 将StudentDTO反向映射为Student类型            Student student = _mapper.Map(entity);            // 添加到集合中            Data.Add(student);            // 返回增加后的数组,这里返回Student            list = await Task.Run>(() =>            {                return Data.GetList();            });            return list;        }    }}

使用Postman进行测试:

返回结果:

这样就实现了映射的反转。

关于"ASP.NET Core如何使用AutoMapper实现实体映射"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

类型 属性 数据 实体 参数 测试 函数 方法 代码 多个 就是 方式 目标 第一次 需求 中实 循环 配置 之间 再次 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 义乌网络安全工程师线上学习 中国用的数据库是美国的吗 更换dns服务器需要多久 教资报名总是显示内部服务器错误 如何自动填充跨行数据库 单县企业诚信积分管理软件开发 亚马逊数据库怎么样 服务器显卡和主板通用吗 fm如何还原官方数据库 职业介绍计算机网络技术没啥用 杨浦区常见网络技术要多少钱 网络安全管理脉络图 互联网科技开发是什么 上海质量网络技术开发优化价格 国家网络安全周 纪录片 软件开发公司图片处理 我的世界服务器功能 国安网络安全部 深圳车牌识别系统软件开发 坐标查询数据库 淘宝服务器放在什么地方 道聚城获取服务器失败 东营纺织软件开发服务 一台服务器两组阵列 云服务器怎么装 脏小豆服务器管理成员 数据库文件怎么打开 网络安全相关的岗位 数据库文本型用什么字母表示 宏业数据库无法连接什么原因
0