1、前言
在之前的博客中,我们通过EFCore
的Scaffold-DbContext
命令一键生成数据库实体类。但在实际业务中,实体类并不能很好地应对所有情况。例如前端页面只需要展示某张表中部分字段的信息,这时如果直接将实体类集合返回给前端界面,就有可能造成数据的冗余和泄露问题。而在某些情况下,前端界面需要展示的字段信息可能并不包含在当前的实体类中。因此在实际业务中,可以考虑定义一系列的DTO
实体类来解决上述问题,这也就涉及到实体类之间的相互转换问题。在ASP.NET Core
中,一般推荐使用AutoMapper
来实现实体转换操作,下面开始介绍它的用法。
2、低效的实体转换操作
这里通过控制台程序来说明,定义一个实体类Person
,其中包含若干属性,代码如下:
namespace MapperApp
{
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Gender { get; set; }
public int Age { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
}
}
Person
中包含一系列属性,但在实际业务中可能只需要显示Name
、Gender
、Age
这3
个属性,这时可以考虑将它们提取出来单独建一个类PersonDto
,代码如下所示:
namespace MapperApp
{
public class PersonDto
{
public string Name { get; set; }
public string Gender { get; set; }
public int Age { get; set; }
}
}
那么如何将Person
转换为PersonDto
呢?低效的做法就是手写转换过程,代码如下所示:
using System;
using System.Collections.Generic;
namespace MapperApp
{
internal class Program
{
static void Main(string[] args)
{
List<Person> pos = new List<Person>
{
new Person { Id = 1, Name = "张三", Gender = "男", Age = 30, Phone = "1111", Email = "1111@qq.com" },
new Person { Id = 2, Name = "李四", Gender = "女", Age = 31, Phone = "2222", Email = "2222@qq.com" },
new Person { Id = 3, Name = "王五", Gender = "男", Age = 32, Phone = "3333", Email = "3333@qq.com" }
};
// 转换为DTO
List<PersonDto> dtos = new List<PersonDto>();
foreach (Person po in pos)
{
dtos.Add(new PersonDto { Name = po.Name, Gender = po.Gender, Age = po.Age });
}
// 打印
foreach (PersonDto dto in dtos)
{
Console.WriteLine(dto.Name + "," + dto.Gender + "," + dto.Age);
}
Console.ReadKey();
}
}
}
运行结果如下所示:
张三,男,30
李四,女,31
王五,男,32
虽然上述方法可以解决问题,但相信你也发现了:如果有多个方法都需要返回DTO
对象,那么这种低效的转换代码就需要进行多次编写,因此上述方法并不是最优方法。
3、AutoMapper下的实体转换操作
现在来看看AutoMapper
是如何处理转换问题的。在工程中使用NuGet
引入如下组件:
AutoMapper
3.1、AutoMapper的基础操作
AutoMapper
中主要使用MapperConfiguration
和IMapper
来进行转换操作,前者负责定义转换规则,后者负责获取转换后的实体,代码如下:
using AutoMapper;
using System;
using System.Collections.Generic;
namespace MapperApp
{
internal class Program
{
static void Main(string[] args)
{
// 创建对象映射工具
MapperConfiguration configuration = new MapperConfiguration(options =>
{
options.CreateMap<Person, PersonDto>().ForMember(dest => dest.Name, e => e.MapFrom(src => src.Name))
.ForMember(dest => dest.Gender, e => e.MapFrom(src => src.Gender))
.ForMember(dest => dest.Age, e => e.MapFrom(src => src.Age));
});
IMapper mapper = configuration.CreateMapper();
// 原始数据
List<Person> pos = new List<Person>
{
new Person { Id = 1, Name = "张三", Gender = "男", Age = 30, Phone = "1111", Email = "1111@qq.com" },
new Person { Id = 2, Name = "李四", Gender = "女", Age = 31, Phone = "2222", Email = "2222@qq.com" },
new Person { Id = 3, Name = "王五", Gender = "男", Age = 32, Phone = "3333", Email = "3333@qq.com" }
};
// 转换为DTO
List<PersonDto> dtos = mapper.Map<List<PersonDto>>(pos);
foreach (PersonDto dto in dtos)
{
Console.WriteLine(dto.Name + "," + dto.Gender + "," + dto.Age);
}
Console.ReadKey();
}
}
}
运行结果如下所示:
张三,男,30
李四,女,31
王五,男,32
在上面的代码中,我们只需要定义Person
转换到PersonDto
的规则即可,AutoMapper
会解析该规则,实现Person
到PersonDto
或List<Person>
到List<PersonDto>
的转换操作。其实上述规则写的有些繁琐,由于Person
和PersonDto
中的字段名称一致,因此也可以使用简易写法,代码如下:
using AutoMapper;
using System;
using System.Collections.Generic;
namespace MapperApp
{
internal class Program
{
static void Main(string[] args)
{
// 创建对象映射工具
MapperConfiguration configuration = new MapperConfiguration(options =>
{
options.CreateMap<Person, PersonDto>();
});
IMapper mapper = configuration.CreateMapper();
// 原始数据
List<Person> pos = new List<Person>
{
new Person { Id = 1, Name = "张三", Gender = "男", Age = 30, Phone = "1111", Email = "1111@qq.com" },
new Person { Id = 2, Name = "李四", Gender = "女", Age = 31, Phone = "2222", Email = "2222@qq.com" },
new Person { Id = 3, Name = "王五", Gender = "男", Age = 32, Phone = "3333", Email = "3333@qq.com" }
};
// 转换为DTO
List<PersonDto> dtos = mapper.Map<List<PersonDto>>(pos);
foreach (PersonDto dto in dtos)
{
Console.WriteLine(dto.Name + "," + dto.Gender + "," + dto.Age);
}
Console.ReadKey();
}
}
}
运行结果如下所示:
张三,男,30
李四,女,31
王五,男,32
3.2、AutoMapper的双向映射
上面的代码定义了Person
到PersonDto
的转换规则,那么PersonDto
到Person
的转换规则又该如何定义呢?我们当然可以手动编写这两者之间的转换规则,代码如下:
using AutoMapper;
using System;
using System.Collections.Generic;
namespace MapperApp
{
internal class Program
{
static void Main(string[] args)
{
// 创建对象映射工具
MapperConfiguration configuration = new MapperConfiguration(options =>
{
// Person到PersonDto规则
options.CreateMap<Person, PersonDto>().ForMember(dest => dest.Name, e => e.MapFrom(src => src.Name))
.ForMember(dest => dest.Gender, e => e.MapFrom(src => src.Gender))
.ForMember(dest => dest.Age, e => e.MapFrom(src => src.Age));
// PersonDto到Person规则
options.CreateMap<PersonDto, Person>().ForMember(dest => dest.Name, e => e.MapFrom(src => src.Name))
.ForMember(dest => dest.Gender, e => e.MapFrom(src => src.Gender))
.ForMember(dest => dest.Age, e => e.MapFrom(src => src.Age));
});
IMapper mapper = configuration.CreateMapper();
// 原始数据
List<Person> list = new List<Person>
{
new Person { Id = 1, Name = "张三", Gender = "男", Age = 30, Phone = "1111", Email = "1111@qq.com" },
new Person { Id = 2, Name = "李四", Gender = "女", Age = 31, Phone = "2222", Email = "2222@qq.com" },
new Person { Id = 3, Name = "王五", Gender = "男", Age = 32, Phone = "3333", Email = "3333@qq.com" }
};
// 转换为DTO
List<PersonDto> dtos = mapper.Map<List<PersonDto>>(list);
// DTO转换为原始数据
List<Person> pos = mapper.Map<List<Person>>(dtos);
foreach (Person po in pos)
{
Console.WriteLine(po.Name + "," + po.Gender + "," + po.Age + "," + po.Phone + "," + po.Email);
}
Console.ReadKey();
}
}
}
运行结果如下所示:
张三,男,30,,
李四,女,31,,
王五,男,32,,
当然也有简便的方法,AutoMapper
提供了一个双向映射的方法ReverseMap()
,代码如下:
using AutoMapper;
using System;
using System.Collections.Generic;
namespace MapperApp
{
internal class Program
{
static void Main(string[] args)
{
// 创建对象映射工具
MapperConfiguration configuration = new MapperConfiguration(options =>
{
options.CreateMap<Person, PersonDto>().ForMember(dest => dest.Name, e => e.MapFrom(src => src.Name))
.ForMember(dest => dest.Gender, e => e.MapFrom(src => src.Gender))
.ForMember(dest => dest.Age, e => e.MapFrom(src => src.Age))
.ReverseMap();
});
IMapper mapper = configuration.CreateMapper();
// 原始数据
List<Person> list = new List<Person>
{
new Person { Id = 1, Name = "张三", Gender = "男", Age = 30, Phone = "1111", Email = "1111@qq.com" },
new Person { Id = 2, Name = "李四", Gender = "女", Age = 31, Phone = "2222", Email = "2222@qq.com" },
new Person { Id = 3, Name = "王五", Gender = "男", Age = 32, Phone = "3333", Email = "3333@qq.com" }
};
// 转换为DTO
List<PersonDto> dtos = mapper.Map<List<PersonDto>>(list);
// DTO转换为原始数据
List<Person> pos = mapper.Map<List<Person>>(dtos);
foreach (Person po in pos)
{
Console.WriteLine(po.Name + "," + po.Gender + "," + po.Age + "," + po.Phone + "," + po.Email);
}
Console.ReadKey();
}
}
}
运行结果也是一样的:
张三,男,30,,
李四,女,31,,
王五,男,32,,
3.3、AutoMapper中字段名称不一致的处理方法
在某些情况下会存在字段名称不一致的问题,现在修改一下PersonDto
的代码,如下所示:
namespace MapperApp
{
public class PersonDto
{
/// <summary>
/// 姓名
/// </summary>
public string PersonName { get; set; }
/// <summary>
/// 性别
/// </summary>
public string PersonGender { get; set; }
/// <summary>
/// 年龄
/// </summary>
public int PersonAge { get; set; }
/// <summary>
/// 信息
/// </summary>
public string PersonInfo { get; set; }
}
}
每个字段名称都加了前缀,同时新增了一个PersonInfo
字段,此时的转换代码如下所示:
using AutoMapper;
using System;
using System.Collections.Generic;
namespace MapperApp
{
internal class Program
{
static void Main(string[] args)
{
// 创建对象映射工具
MapperConfiguration configuration = new MapperConfiguration(options =>
{
options.CreateMap<Person, PersonDto>().ForMember(dest => dest.PersonName, e => e.MapFrom(src => src.Name))
.ForMember(dest => dest.PersonGender, e => e.MapFrom(src => src.Gender))
.ForMember(dest => dest.PersonAge, e => e.MapFrom(src => src.Age))
.ForMember(dest => dest.PersonInfo, e => e.MapFrom(src => $"姓名:{src.Name},性别:{src.Gender},年龄:{src.Age}"))
.ReverseMap();
});
IMapper mapper = configuration.CreateMapper();
// 原始数据
List<Person> pos = new List<Person>
{
new Person { Id = 1, Name = "张三", Gender = "男", Age = 30, Phone = "1111", Email = "1111@qq.com" },
new Person { Id = 2, Name = "李四", Gender = "女", Age = 31, Phone = "2222", Email = "2222@qq.com" },
new Person { Id = 3, Name = "王五", Gender = "男", Age = 32, Phone = "3333", Email = "3333@qq.com" }
};
// 转换为DTO
List<PersonDto> dtos = mapper.Map<List<PersonDto>>(pos);
foreach (PersonDto dto in dtos)
{
Console.WriteLine("------------------------------");
Console.WriteLine(dto.PersonName + "\n" + dto.PersonGender + "\n" + dto.PersonAge + "\n" + dto.PersonInfo);
}
Console.ReadKey();
}
}
}
运行结果如下所示:
------------------------------
张三
男
30
姓名:张三,性别:男,年龄:30
------------------------------
李四
女
31
姓名:李四,性别:女,年龄:31
------------------------------
王五
男
32
姓名:王五,性别:男,年龄:32
其实处理方法很简单,就是调用ForMember
方法指定要映射的字段名称即可。
3.4、AutoMapper中的空值处理
在某些情况下,源数据中的部分字段值可能为空,例如下面的代码中两条记录的Gender
值为空:
List<Person> pos = new List<Person>
{
new Person { Id = 1, Name = "张三", Gender = null, Age = 30, Phone = "1111", Email = "1111@qq.com" },
new Person { Id = 2, Name = "李四", Gender = "女", Age = 31, Phone = "2222", Email = "2222@qq.com" },
new Person { Id = 3, Name = "王五", Gender = null, Age = 32, Phone = "3333", Email = "3333@qq.com" }
};
此时我们希望转换后的实体能够使用一些特定值来代替空值,例如Gender
为空时显示性别未知
。AutoMapper
支持在转换规则中使用NullSubstitute
方法对空值进行处理,代码如下:
using AutoMapper;
using System;
using System.Collections.Generic;
namespace MapperApp
{
internal class Program
{
static void Main(string[] args)
{
// 创建对象映射工具
MapperConfiguration configuration = new MapperConfiguration(options =>
{
options.CreateMap<Person, PersonDto>().ForMember(dest => dest.Name, e => e.MapFrom(src => src.Name))
.ForMember(dest => dest.Gender, e => e.NullSubstitute("性别未知"))
.ForMember(dest => dest.Age, e => e.MapFrom(src => src.Age))
.ReverseMap();
});
IMapper mapper = configuration.CreateMapper();
// 原始数据
List<Person> pos = new List<Person>
{
new Person { Id = 1, Name = "张三", Gender = null, Age = 30, Phone = "1111", Email = "1111@qq.com" },
new Person { Id = 2, Name = "李四", Gender = "女", Age = 31, Phone = "2222", Email = "2222@qq.com" },
new Person { Id = 3, Name = "王五", Gender = null, Age = 32, Phone = "3333", Email = "3333@qq.com" }
};
// 转换为DTO
List<PersonDto> dtos = mapper.Map<List<PersonDto>>(pos);
foreach (PersonDto dto in dtos)
{
Console.WriteLine(dto.Name + "," + dto.Gender + "," + dto.Age);
}
Console.ReadKey();
}
}
}
运行结果如下所示:
张三,性别未知,30
李四,女,31
王五,性别未知,32
3.5、AutoMapper中映射前后的处理
AutoMapper
支持在映射前后对数据进行操作。BeforeMap
允许开发者在映射之前进行操作,AfterMap
允许开发者在映射之后进行操作,下面的代码演示了在映射之前年龄增加10
岁,映射之后再将年龄增加10
岁:
using AutoMapper;
using System;
using System.Collections.Generic;
namespace MapperApp
{
internal class Program
{
static void Main(string[] args)
{
// 创建对象映射工具
MapperConfiguration configuration = new MapperConfiguration(options =>
{
options.CreateMap<Person, PersonDto>().ForMember(dest => dest.Name, e => e.MapFrom(src => src.Name))
.ForMember(dest => dest.Gender, e => e.MapFrom(src => src.Gender))
.ForMember(dest => dest.Age, e => e.MapFrom(src => src.Age))
.BeforeMap((src, dest) =>
{
// 映射之前年龄增加10岁
src.Age += 10;
})
.AfterMap((src, dest) =>
{
// 映射之后年龄增加10岁
dest.Age += 10;
})
.ReverseMap();
});
IMapper mapper = configuration.CreateMapper();
// 原始数据
List<Person> pos = new List<Person>
{
new Person { Id = 1, Name = "张三", Gender = "男", Age = 30, Phone = "1111", Email = "1111@qq.com" },
new Person { Id = 2, Name = "李四", Gender = "女", Age = 31, Phone = "2222", Email = "2222@qq.com" },
new Person { Id = 3, Name = "王五", Gender = "男", Age = 32, Phone = "3333", Email = "3333@qq.com" }
};
// 转换为DTO
List<PersonDto> dtos = mapper.Map<List<PersonDto>>(pos);
foreach (PersonDto dto in dtos)
{
Console.WriteLine(dto.Name + "," + dto.Gender + "," + dto.Age);
}
Console.ReadKey();
}
}
}
运行结果如下所示:
张三,男,50
李四,女,51
王五,男,52
3.6、AutoMapper中的条件过滤
AutoMapper
也支持条件过滤。这里的过滤并不是指剔除数据记录,而是隐藏被过滤的字段值。下面代码演示了当Gender="男"
时才显示Gender
字段值,主要通过Condition
方法实现:
using AutoMapper;
using System;
using System.Collections.Generic;
namespace MapperApp
{
internal class Program
{
static void Main(string[] args)
{
// 创建对象映射工具
MapperConfiguration configuration = new MapperConfiguration(options =>
{
options.CreateMap<Person, PersonDto>().ForMember(dest => dest.Name, e => e.MapFrom(src => src.Name))
.ForMember(dest => dest.Gender, e => e.Condition(src => src.Gender == "男"))
.ForMember(dest => dest.Age, e => e.MapFrom(src => src.Age))
.ReverseMap();
});
IMapper mapper = configuration.CreateMapper();
// 原始数据
List<Person> pos = new List<Person>
{
new Person { Id = 1, Name = "张三", Gender = "男", Age = 30, Phone = "1111", Email = "1111@qq.com" },
new Person { Id = 2, Name = "李四", Gender = "女", Age = 31, Phone = "2222", Email = "2222@qq.com" },
new Person { Id = 3, Name = "王五", Gender = "男", Age = 32, Phone = "3333", Email = "3333@qq.com" }
};
// 转换为DTO
List<PersonDto> dtos = mapper.Map<List<PersonDto>>(pos);
foreach (PersonDto dto in dtos)
{
Console.WriteLine(dto.Name + "," + dto.Gender + "," + dto.Age);
}
Console.ReadKey();
}
}
}
运行结果如下所示,可以发现李四的性别并未显示出来:
张三,男,30
李四,,31
王五,男,32
3.7、AutoMapper映射模块的单独配置
在实际开发过程中,为了方便后续的维护和管理,我们一般会把AutoMapper
的配置规则写在一个单独的类中,具体方法如下,首先新建ObjectMappingProfile
类,该类继承Profile
,然后在构造函数中定义转换规则,代码如下:
using AutoMapper;
namespace MapperApp
{
public class ObjectMappingProfile : Profile
{
public ObjectMappingProfile()
{
CreateMap<Person, PersonDto>().ForMember(dest => dest.Name, e => e.MapFrom(src => src.Name))
.ForMember(dest => dest.Gender, e => e.MapFrom(src => src.Gender))
.ForMember(dest => dest.Age, e => e.MapFrom(src => src.Age))
.ReverseMap();
}
}
}
然后通过AddProfile
方法将规则文件加载进来即可,代码如下:
using AutoMapper;
using System;
using System.Collections.Generic;
namespace MapperApp
{
internal class Program
{
static void Main(string[] args)
{
// 创建对象映射工具
MapperConfiguration configuration = new MapperConfiguration(options => options.AddProfile(new ObjectMappingProfile()));
IMapper mapper = configuration.CreateMapper();
// 原始数据
List<Person> pos = new List<Person>
{
new Person { Id = 1, Name = "张三", Gender = "男", Age = 30, Phone = "1111", Email = "1111@qq.com" },
new Person { Id = 2, Name = "李四", Gender = "女", Age = 31, Phone = "2222", Email = "2222@qq.com" },
new Person { Id = 3, Name = "王五", Gender = "男", Age = 32, Phone = "3333", Email = "3333@qq.com" }
};
// 转换为DTO
List<PersonDto> dtos = mapper.Map<List<PersonDto>>(pos);
foreach (PersonDto dto in dtos)
{
Console.WriteLine(dto.Name + "," + dto.Gender + "," + dto.Age);
}
Console.ReadKey();
}
}
}
运行结果如下所示:
张三,男,30
李四,女,31
王五,男,32
4、ASP.NET Core中使用AutoMapper
上面的代码都是基于控制台程序,下面来介绍一下如何在ASP.NET Core
中使用AutoMapper
。还是使用之前的Author
数据表。
Author
表数据如下:
Id | Name | Gender | Age | |
---|---|---|---|---|
1 | 张三 | 男 | 35 | 11111111@qq.com |
2 | 李四 | 女 | 40 | 22222222@qq.com |
3 | 王五 | 男 | 37 | 33333333@qq.com |
Author
代码如下:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
// Code scaffolded by EF Core assumes nullable reference types (NRTs) are not used or disabled.
// If you have enabled NRTs for your project, then un-comment the following line:
// #nullable disable
namespace App.Models
{
public partial class Author
{
public Author()
{
Book = new HashSet<Book>();
}
[Key]
public int Id { get; set; }
[StringLength(20)]
public string Name { get; set; }
[StringLength(2)]
public string Gender { get; set; }
public int? Age { get; set; }
[StringLength(30)]
public string Email { get; set; }
[InverseProperty("Author")]
public virtual ICollection<Book> Book { get; set; }
}
}
4.1、引入AutoMapper组件
使用NuGet
引入AutoMapper
组件:
AutoMapper
AutoMapper.Extensions.Microsoft.DependencyInjection
4.2、创建DTO实体类
新建实体类AuthorDto
,代码如下:
namespace App.Dtos
{
public class AuthorDto
{
public string Name { get; set; }
public string Gender { get; set; }
public string Email { get; set; }
}
}
4.3、配置AutoMapper转换规则
添加ObjectMappingProfile
类配置映射规则,代码如下:
using App.Dtos;
using App.Models;
using AutoMapper;
namespace App
{
public class ObjectMappingProfile : Profile
{
public ObjectMappingProfile()
{
CreateMap<Author, AuthorDto>().ForMember(dest => dest.Name, e => e.MapFrom(src => src.Name))
.ForMember(dest => dest.Gender, e => e.MapFrom(src => src.Gender))
.ForMember(dest => dest.Email, e => e.MapFrom(src => src.Email))
.ReverseMap();
}
}
}
4.4、注册AutoMapper服务
在Startup.cs
中添加AutoMapper
服务,代码如下:
using App.Context;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace App
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// 添加控制器
services.AddControllers();
// 添加数据库上下文
services.AddDbContext<DaoDbContext>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("ConnectionString"));
});
// 添加AutoMapper
services.AddAutoMapper(typeof(ObjectMappingProfile).Assembly);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
4.5、注入IMapper接口
最后在Controller
的构造函数中注入IMapper
接口即可,代码如下:
using App.Context;
using App.Dtos;
using App.Models;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;
namespace App.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class AuthorController : ControllerBase
{
protected readonly DaoDbContext _dbContext;
protected readonly IMapper _mapper;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="dbContext">数据库上下文</param>
/// <param name="mapper">对象映射器</param>
public AuthorController(DaoDbContext dbContext, IMapper mapper)
{
_dbContext = dbContext;
_mapper = mapper;
}
/// <summary>
/// 查询全部Author实体集合
/// </summary>
/// <returns>Author实体集合</returns>
[HttpGet]
public ActionResult<List<AuthorDto>> GetAuthors()
{
List<Author> authors = _dbContext.Set<Author>().ToList();
return _mapper.Map<List<AuthorDto>>(authors);
}
/// <summary>
/// 根据性别查询Author实体集合
/// </summary>
/// <param name="gender">性别</param>
/// <returns>Author实体集合</returns>
[HttpGet]
public ActionResult<List<AuthorDto>> GetAuthorsByGender(string gender)
{
if (string.IsNullOrEmpty(gender) || string.IsNullOrWhiteSpace(gender))
{
return BadRequest("参数错误");
}
List<Author> authors = _dbContext.Set<Author>().Where(p => p.Gender == gender).ToList();
return _mapper.Map<List<AuthorDto>>(authors);
}
/// <summary>
/// 根据Id查询Author实体
/// </summary>
/// <param name="id">Id</param>
/// <returns>Author实体</returns>
[HttpGet]
public ActionResult<AuthorDto> GetAuthorById(int id)
{
if (id <= 0)
{
return BadRequest("参数错误");
}
Author author = _dbContext.Set<Author>().Find(id);
return _mapper.Map<AuthorDto>(author);
}
}
}
GetAuthors
运行结果如下所示:
[
{
"name": "张三",
"gender": "男",
"email": "11111111@qq.com"
},
{
"name": "李四",
"gender": "女",
"email": "22222222@qq.com"
},
{
"name": "王五",
"gender": "男",
"email": "33333333@qq.com"
}
]
GetAuthorsByGender
运行结果如下所示:
[
{
"name": "张三",
"gender": "男",
"email": "11111111@qq.com"
},
{
"name": "王五",
"gender": "男",
"email": "33333333@qq.com"
}
]
GetAuthorById
运行结果如下所示:
{
"name": "张三",
"gender": "男",
"email": "11111111@qq.com"
}
以上就是在ASP.NET Core
中使用AutoMapper
的具体流程。
5、结语
本文主要介绍了AutoMapper
的部分使用方法。有一些同志也问过:项目中一定要使用AutoMapper
在对象之间转来转去吗?以个人体验来说,我认为不一定非要使用AutoMapper
。对于一些赶进度、规模又不是很大的工程来说,建立DTO
对象反而会增加工作量,还不如直接使用EFCore
生成的实体类,这样方便又快速。如果项目规模到达一定程度,同时开发组里希望遵循一定的项目规范,那么建立诸如DTO
、VO
之类的实体类,通过AutoMapper
实现相互转换还是有必要的。