在web应用程序中,我们通常把系统结构分为三层/多层。
其中Model层存放我们的实体类.
UI层,业务逻辑层,数据访问层均引用了Model层.
在前台页面发送一个http请求,后台处理后返回相应的json数据.也就是对应的实体..
比如EF中的Model,都是根据业务逻辑来建立的实体类,也可以称为是业务对象模型(领域模型)。
那么在这里DTO又有什么作用?
DTO:(Data Transfer Object) 数据传输对象.是为了隔离领域模型(Domain Model).
让业务模型的更改,不会直接影响到UI,保持Domain Model 的安全,不暴露业务逻辑。
这里的业务对象模型,是根据业务逻辑来建立,我们通过代码生成器来生成程序的实体类。
强调了数据表与类的映射关系。Domain Model主要是面向业务的.
而DTO也是模型,可以称为视图模型,是根据UI需求来建立的。(按需索取)
比如:一个用户表有很多字段,但我在前台页面只需要显示用户[姓名、年龄、电话号码、地址] 就好了。
如果我们把这个实体查询出来 UserInfo user = Find(xx); 直接序列化Json返回给前台,字段就太多了。
不需要的字段我们不返回就好了,所以DTO这个类也不需要包含其他的字段(属性)。
public class PersonDTO { public string Name{get;set;} //UI需要的字段属性 }
建立DTO类,也避免了linq自定义查询投影实体类的异常问题.
AutoMapper:用户模型之前的相互映射。(源对象转为目标对象)
方便我们映射的操作
1.从Nuget中安装AutoMapper
2.配置AutoMapper
3.初始化映射
public class UserInfo { public string UserID { get; set; } public string UserName { get; set; } public string UserPwd { get; set; } public int Age { get; set; } public string Name { get; set; } public DateTime Birth { get; set; } public string Address { get; set; } public string Tel { get; set; } } public class UserInfo_DTO { public string Name { get; set; } public int Age { get; set; } public string Address { get; set; } public int Birth_Year { get; set; } public int Birth_Month { get; set; } }
public class MapperProfile : Profile { //所有继承自Profile类的子类都是一个映射集合 protected override void Configure() { CreateMap(); //映射,需要将出生日期映射到DTO中为年、月 CreateMap() .ForMember(dto => dto.Birth_Month, opt => opt.MapFrom(src => src.Birth.Month)) .ForMember(dto => dto.Birth_Year, opt => opt.MapFrom(src => src.Birth.Year)); } }
static void Main(string[] args) { Mapper.Initialize(m => m.AddProfile()); //Entity Model UserInfo user = new UserInfo(); user.Name = "xiaoqiu"; user.Age = 21; user.Address = "湖北襄阳"; user.Birth = new DateTime(1995, 8, 18); //DTO: Data Transfer Object UserInfo_DTO user_dto = Mapper.Map(user); Console.WriteLine(user_dto.Name); Console.WriteLine("出生年:" + user_dto.Birth_Year + "年" + user_dto.Birth_Month + "月"); }