普通的模型映射
现在有两个类,实体类Student和返回展示的 View类StudentView
![v2-008dc29f27d75a4d5b906c361a77226b_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/7e29e07e3857f9bc4749ee871daeb8d1.jpeg)
![v2-2d89042ba9fe0d172fd8b67f93876e24_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/27eeb6c4b71fe4b80332a0c264102c5f.jpeg)
两个实体类字段还基本可以,不是很多,假如字段非常非常多,还需要手动去赋值的话,简直太痛苦了。
![v2-9d71533046b18e1be146a7f116db14c2_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/21b61df5ed079f6182eeb5e4c9a3e83f.jpeg)
![v2-007f367d6b29137721d5399151c356f1_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/99b2a6635f226639530e8a9766ebbc0b.jpeg)
想了想这才是一个方法,一般的系统都会少则几十,多则上百个这样的方法,这还不算,大家肯定遇到过一个情况,如果有一天要在页面多显示一个字段,噗!不是吧,首先要存在数据库,然后在该实体类就应该多一个,然后再在每一个赋值的地方增加一个,而且也没有更好的办法不是,一不小心就少了一个,然后被产品测试说咱们不细心,心塞哟,别慌!神器来了,一招搞定。
先来引入DTO讲解
我们已经知道了ORM(Object Relational Mapping)映射,是一种对象关系的映射,对象-关系映射(ORM)系统一般以中间件的形式存在,主要实现程序对象到关系数据库数据的映射。
而Automapper是一种实体转换关系的模型,AutoMapper是一个.NET的对象映射工具。主要作用是进行领域对象与模型(DTO)之间的转换、数据库查询结果映射至实体对象。
引入AutoMapper的包
![v2-eaae9bb9f3b68a3d4944487ac099de47_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/7f0476ff9cd5c609d1fcbf95929b697e.jpeg)
在Services层中引用Nuget包,AutoMapper 和 AutoMapper.Extensions.Microsoft.DependencyInjection
AutoMapper.Extensions.Microsoft.DependencyInjection,这个是用来配合依赖注入的,
在项目当中,都使用依赖注入,尽量不要用new 来实例化,导致层耦合
添加映射文件 AutomapperConfig.cs
在web项目中,新建文件夹,Automapper,添加配置映射配置文件AutomapperConfig.cs,继承自Profile类,用来配置所有的映射关系。
![v2-aef15473b6188e54ebdc27ddd94ac2be_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/55b07cda437377fddce7a73d07ff5367.jpeg)
这里的 Profile有什么用呢,是 services.AddAutoMapper他会自动找到所有继承了Profile的类然后进行配置。我这个类是放在Web层的,如果Profile配置放在其他的层比如Service层,如下图:直接耦合
![v2-f11e42dd7f35eaa277c0f7924353dbe7_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/f5bdbe73836db60c1cf260578d15e438.jpeg)
使用AutoMapper实现模型映射,并注入
那此时Startup类里面的配置就可以写成 services.AddAutoMapper(Assembly.Load("Service"));它会自动加载Service的程序集并从这里面找到继承了profile类的配置实现。
如果profile配置放在了web层,那就相当于把配置类和Service层进行了解耦,那么配置中可以写
![v2-e1522d96a16d9cfc53e813d6a1bccd3f_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/317328f3cb6da0a55a9b00f32950008a.jpeg)
实现接口的方法中使用mapper
![v2-37c352e7f0d07dd4e850a047e9fddf1f_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/49863a99eb9af6ad37e0f14cefeac762.jpeg)
控制器调用接口,并传输数据,最终在index页面上显示:
![v2-2e37ebe1e35a377826853f09036ab33e_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/aef28fd9a2d88a5d77218d0844f45e42.jpeg)
![v2-9e292fe06ee1d61ca594dbc1f58dec29_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/179eb60aa27a783fd742550f78cf1704.jpeg)
前端显示:
![v2-6e17175b128d086ab5cb438803c099b3_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/db11c7a791861dec460a49b5310ba57f.jpeg)
是不是少了一个Name呢,原因是,我们配置的source和destination两个类的字段不是完全相同的,但是有时候这两个字段实际上是相同的。
我们可以,加上配置:
![v2-4d35a98a02f666249789a51ff6a5d986_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/2a373a4928e708a112b94c1bfdbf867a.jpeg)
如果不想映射某个字段:我们还可以:
![v2-1045dbb21935742a3342ec11bc6c22ba_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/d8f70d2687d237ee62165dd08dea6418.jpeg)
这样子,我们完成了映射类的配置:忽略age的映射,并将原始类的name给到StudentView的StudentName,这样子,前端显示肯定是18消失了,转而出现了张国荣字样,我们来看看是不是呢?
![v2-830dd8f1989501a65c3a5c888370d100_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/ef82fbd65fab5ef872dd054367f996b1.jpeg)
哦?张国荣字样确实出来了,可为什么会多出个0呢?
原因是,在C#的数据类型当中,int类型属于值类型,是不能为空的,默认给了0,我们尝试将model实体类的age改为可空类型试试。
![v2-9a8521ea3d13fd32777c8663c478d50d_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/319ee60d2634ebf59d2c94da5066c199.jpeg)
前端测试如下:
![v2-eeaec0263a1dbd7e44e816787a564e5b_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/84e5a5cd7464f077fee11652860249a3.jpeg)
果然age消失了。好了今天的学习就到这里结束了,欢迎关注微信公众号:dotNET学习天地
一起学习和进步,与君共勉之。