目录
简介
我们最常见项目架构就是三层架构,其中必少不了Model,但在一个项目中,肯定不止用一种模型
比如DataModel(数据模型),Dto(数据传输对象),ViewModel(视图模型)
其中各个模型的作用
DataModel用于DAL层与数据库数据传输
Dto用于BLL层与UI层数据传输
ViewModel用于UI层的输入验证和数据展示
可能有人会说,我只用一个模型不行吗?
答案是可以的,只用DataModel也是,但这只是适用于小项目,没有太多数据表。如果有很多表并且字段很多时,传输过程可能就传输了一些无用的数据,这就是Dto解决的问题,当然不止于此。
AutoMapper使用
在模型转化时,手写代码虽然简单但是很枯燥,我们可以使用模型映射工具自动转换模型,AutoMapper就是一个很好的模型映射工具,相信很多人都用过了,不懂的可以点击这里
在两个模型的字段类型和名称相同的情况下,处理起来非常简单
只要在Global文件的Application_Start中添加映射关系即可,例如这样
AutoMapper.Mapper.Initialize(m =>
{
m.CreateMap<UserInfo, UserInfoDto>().ReverseMap();
});
用法,模型的相互转换
UserInfo userInfo = new UserInfo
{
Id = 1001,
Name = "haha",
Pwd = "123",
Age = 18,
IsDeleted = false,
CreatedTime = DateTime.Now
};
UserInfoDto userInfoDto = AutoMapper.Mapper.Map<UserInfoDto>(userInfo);
UserInfo user = AutoMapper.Mapper.Map<UserInfo>(userInfoDto);
多模型设计思路
项目设计中使用EF访问数据库,我们可以通过EF获取实体模型的数据,然后通过T4模板自动代码
可以自动生成Dto,ViewModel,还可以自动生成模型映射关系和模型转换方法
多模型项目设计
下面只显示Model部分
其中Wang.OA.Model.Conversion存放模型映射关系和模型转换方法
在开发中不可能一次性把Dto,或者ViewModel写好,所以我们可以用partial标记来生成所需的Dto和ViewModel
当然这部分模型只是一个没有任何字段的类,创建Dto和ViewModel还要根据实际的业务来创建
创建Dto的T4代码
通过EF获取所有的模型,生成所有的Dto
<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#><#@
output extension=".cs"#>
<#
const string inputFile = @"..\\Wang.OA.Model\\DataModel.edmx";
var code = new CodeGenerationTools(this);
var loader = new MetadataLoader(this);
var region = new CodeRegion(this,1);
var ef = new MetadataTools(this);
var ItemCollection = loader.CreateEdmItemCollection(inputFile);
string namespaceName = code.VsNamespaceSuggestion();
var fileManager = EntityFrameworkTemplateFileManager.Create(this);
#>
namespace Wang.OA.Dto
{
<#
foreach (var entity in ItemCollection.GetItems<EntityType>().OrderBy(e=>e.Name))
{
#>
public partial class <#=entity.Name#>Dto
{
}
<#}#>
}
生成
生成的类就是一个没有任何字段的类
我们可以根据实际情况创建Dto
UserInfoDto
public partial class UserInfoDto
{
public int Id { get; set; }
public string Name { get; set; }
public string Pwd { get; set; }
public string ShowName { get; set; }
public string Remark { get; set; }
}
创建ViewModel的T4代码
这代码也是类似上面的,上面重复T4代码的就不写了
namespace Wang.OA.ViewModel
{
<#
foreach (var entity in ItemCollection.GetItems<EntityType>().OrderBy(e=>e.Name))
{
#>
public partial class <#=entity.Name#>ViewModel
{
}
<#}#>
}
生成的同样是没有任何字段的类
我们可以添加一个ViewModel类,添加模型验证,例如
public partial class UserInfoViewModel
{
public int Id { get; set; }
[Display(Name = "用户名")]
[Required]
public string Name { get; set; }
[Display(Name = "密码")]
[Required]
public string Pwd { get; set; }
[Display(Name = "姓名")]
public string ShowName { get; set; }
[Display(Name = "描述")]
public string Remark { get; set; }
}
接下来就是创建模型映射关系了
在Wang.OA.Model.Conversion项目中添加AutoMapper包
AutoMapperConfigMap文件用于创建模型映射关系
Conversion文件用于创建模型转换的方法
创建模型映射关系的T4代码
上面重复的省略
using System;
using Wang.OA.Model;
using Wang.OA.Dto;
using Wang.OA.ViewModel;
using AutoMapper;
namespace Wang.OA.Model
{
public static class AutoMapperConfigMap
{
public static Action<IMapperConfigurationExpression> CreateMap()
{
Action<IMapperConfigurationExpression> config = m =>
{
<#
foreach (var entity in ItemCollection.GetItems<EntityType>().OrderBy(e=>e.Name))
{
#>
m.CreateMap<<#=entity.Name#>, <#=entity.Name#>Dto>().ReverseMap();
m.CreateMap<<#=entity.Name#>Dto, <#=entity.Name#>ViewModel>().ReverseMap();
<#}#>
};
return config;
}
}
}
创建模型转换方法的T4代码
如果模型转换方法像上面的写法还是有些麻烦,
UserInfoDto userInfoDto = AutoMapper.Mapper.Map<UserInfoDto>(userInfo);
UserInfo user = AutoMapper.Mapper.Map<UserInfo>(userInfoDto);
如果能写出扩展方法就更好了,像这样
UserInfoDto userInfoDto = userInfo.ToDto();
UserInfo userInfo2 = userInfoDto.ToDataModel();
当然是可以实现的,我们还是用T4代码批量生成、
上面重复的省略
using Wang.OA.Model;
using Wang.OA.Dto;
using Wang.OA.ViewModel;
using AutoMapper;
namespace Wang.OA.Model
{
public static partial class ModelExtensions
{
<#
foreach (var entity in ItemCollection.GetItems<EntityType>().OrderBy(e=>e.Name))
{
#>
#region <#=entity.Name#>
public static <#=entity.Name#>Dto ToDto(this <#=entity.Name#> dataModel) => Mapper.Map<<#=entity.Name#>Dto>(dataModel);
public static <#=entity.Name#> ToDataModel(this <#=entity.Name#>Dto dto) => Mapper.Map<<#=entity.Name#>>(dto);
public static <#=entity.Name#>ViewModel ToViewModel(this <#=entity.Name#>Dto dto) => Mapper.Map<<#=entity.Name#>ViewModel>(dto);
public static <#=entity.Name#>Dto ToDto(this <#=entity.Name#>ViewModel viewModel) => Mapper.Map<<#=entity.Name#>Dto>(viewModel);
#endregion <#=entity.Name#>
<#}#>
}
}
生成的代码
一个模型包含了4个方法,分别为
DataModel转Dto
Dto转DataModel
Dto转ViewModel
ViewModel转Dto
AutoMapper初始化设置
最后在Global文件的Application_Start中添加AutoMapper的初始化
AutoMapper.Mapper.Initialize(AutoMapperConfigMap.CreateMap());
设计完成
这样使用起来就很舒服了
UserInfo userInfo = new UserInfo()
{
Id = 1001,
Name = "haha",
Pwd = "123",
ShowName = "哈哈",
DelFlag = 0,
Remark="我是哈哈",
ModfiedOn = DateTime.Now,
SubTime = DateTime.Now
};
UserInfoDto userInfoDto = userInfo.ToDto();
UserInfo userInfo2 = userInfoDto.ToDataModel();
UserInfoViewModel userInfoViewModel = userInfoDto.ToViewModel();
UserInfoDto userInfoDto2 = userInfoViewModel.ToDto();
如果大家觉得写的不好的,大家多多指教,谢谢。