数据库的实体模型和视图模型进行分离

数据库持久化对象(Persistent Object):顾名思义,这个对象是用来将我们的数据持久化到数据库,一般来说,持久化对象中的字段会与数据库中对应的 table 保持一致。

视图对象(View Object):视图对象 VO 是面向前端用户页面的,一般会包含呈现给用户的某个页面/组件中所包含的所有数据字段信息。

数据传输对象(Data Transfer Object):数据传输对象 DTO 一般用于前端展示层与后台服务层之间的数据传递,以一种媒介的形式完成 数据库持久化对象 与 视图对象 之间的数据传递。

NuGet

通过 NuGet 安装 AutoMapper 的包。

AutoMapper 
AutoMapper.Extensions.Microsoft.Dependencylnjection


配置对象转换

创建MappingProfile继承抽象类 Profile

using AutoMapper;
using Snblog.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace Snblog.Enties.AutoMapper
{
public class MappingProfile : Profile
{
/// <summary>
/// 配置构造函数,用来创建关系映射
/// </summary>
public MappingProfile()
{
//构建实体映射规则添加映射对象
//如两个实体字段一致可直接映射关系
//SnUser原对象类型,SnUserDto 目标对象类型 ReverseMap,可相互转换
CreateMap<SnUser, SnUserDto>().ReverseMap();
//CreateMap<SnUser, SnUserDto>();
//CreateMap<SnUserDto, SnUser>();
}
}
}


表实体

在转化的时候只有名字相同的字段才会成功附上对应的值。

数据库实体

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace Snblog.Models
{
public partial class SnUser
{
public int UserId { get; set; }
public string UserIp { get; set; }
public string UserName { get; set; }
public string UserEmail { get; set; }
public string UserPwd { get; set; }
public string UserPhoto { get; set; }
public string UserTime { get; set; }
public string UserNickname { get; set; }
public string UserBrief { get; set; }
}
}


视图模型

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace Snblog.Models
{
public partial class SnUserDto
{
public int UserId { get; set; }
public string UserIp { get; set; }
public string UserName { get; set; }
public string UserEmail { get; set; }
public string UserPwd { get; set; }
public string UserPhoto { get; set; }
public string UserTime { get; set; }
public string UserNickname { get; set; }
public string UserBrief { get; set; }
}
}


注册服务

            #region 实体映射
services.AddAutoMapper(typeof(MappingProfile));
#endregion


自动化注册 1

            //自动化注册
//Assembly.Load() 里面传的是当前项目的名称,或者类库的名称。获取当前项目下的所有类文件。
//通过 Lamda 表达式 Where 找到所有以 Mapper 结尾的文件。
//这样就可以自动注册项目内的所有 Mapper 文件了。
services.AddAutoMapper(
Assembly.Load("Snblog.Enties").GetTypes()
.Where(t => t.FullName.EndsWith("Mapper"))
.ToArray()
);


自动化注册 2

添加接口类 IProfile

    public interface IProfile
{

}


在所有的 Mapper 类里面,实现这个接口。

    public class UserMapper : Profile, IProfile
{
public UserMapper()
{
CreateMap<UserDto, User>();
CreateMap<User, UserViewModel>()
.BeforeMap((u, v) => u.Remark = "Good")
.ForMember(v => v.DepartmentId, u => u.MapFrom(user => user.DepartmentId))
.ForMember(v => v.DepartmentName, u => u.MapFrom(user => user.DepartmentInfo.Name))
.AfterMap((u, v) => u.Age++);
}
}


再通过查找所有实现了 IProfile 接口的类,就可以找到所有的 Mapper 对象。

( Profile 是 AutoMapper 组件里的接口,必须自定义项目中的唯一标记。)

创建 MapperRegister 类,实现获取所有的 Mapper 对象。

    public class MapperRegister
{
/// <summary>
/// 通过反射自动化注册
/// </summary>
/// <returns></returns>
public static Type[] MapType()
{
Assembly ass = Assembly.GetAssembly(typeof(IProfile));
Type[] types = ass.GetTypes();

List<Type> allList = new List<Type>();

foreach (Type item in types)
{
if (item.IsInterface) continue;//判断是否是接口
Type[] ins = item.GetInterfaces();
foreach (Type ty in ins)
{
if (ty == typeof(IProfile))
{
allList.Add(item);
}
}
}
Type[] alltypes = allList.ToArray();
return alltypes;
}

}


修改 StrartUp 类,调整注册方式。

        public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
//services.AddAutoMapper(typeof(UserMapper));
//自动化注册
services.AddAutoMapper(MapperRegister.MapType());

}


这样就可以每次添加 Mapper 类的时候,只需要添加 IProfile 标记,就可以自动注册了。

应用

入参控制好 Add/Up Dto 转数据实体。

返回参数 数据实体转Dto

 // 创建一个字段来存储mapper对象
private readonly IMapper _mapper;

public SnUserService(IMapper mapper)
{
_service = service;
_mapper = mapper;
}
//更新-转数据实体
var model = _mapper.Map<SnUser>(user);
int da = await CreateService<SnUser>().UpdateAsync(model);

//查询- 数据库实体转Dto
public async Task<List<SnUserDto>> AsyGetUser()
{
var user = await _service.SnUser.ToListAsync();
return _mapper.Map<List<SnUserDto>>(user);
}