資料庫的實體模型和視圖模型進行分離
資料庫持久化對象(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);
}