不用EF框架,完成完美实体映射,且便于维护!(AutoMapper,petapoco)
最近,需要搭建一个新项目,在需求分析时确定数据库中需要创建多个存储过程。所以如果还是用原来EF框架生成ADO.net实体模型的话,不利于修改。
主要是解决以下两个问题:
1、比如前端需要一个值,如果存储过程没有返回,那么在修改存储过程后就得更新实体。很麻烦。
2、前端所需数据类型和返回数据类型不同时直接能映射不需要循环处理。
下面做一个简单的用法介绍(以机场数据为例):
第一个问题:
1、首先用petapoco链接数据库
下载链接:http://pan.baidu.com/s/1dFEfzSd
将文件下载后放在一个文件夹中,然后再这个文件夹中创建一个类文件用于创建与数据链接的桥梁。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Web; 7 using PetaPoco; 8 9 namespace Entity.Models 10 { 11 public class LxaAirportStatistics 12 { 13 public static Database Db 14 { 15 get 16 { 17 if (HttpContext.Current.Items["CurrentDb"] == null) 18 { 19 var retval = new Database("AirportEntity"); 20 HttpContext.Current.Items["CurrentDb"] = retval; 21 return retval; 22 } 23 return (Database)HttpContext.Current.Items["CurrentDb"]; 24 } 25 } 26 27 } 28 }
文件中Database的name与web.config中数据库中链接字符串的name一样。
2、现在数据库链接创建好了,就需要创建一个model类用于对数据建立关系。model类字段名称、类型必须和数据库字段名称、类型一致。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace Entity 7 { 8 public class Airport 9 { 10 public string Airport_DM { get; set; } 11 public int? Area_DM { get; set; } 12 public string JC { get; set; } 13 public string QC { get; set; } 14 public string TestCol { get; set; } 15 } 16 }
至此,数据库链接和对应关系都创建好了。第一个问题已经解决?有人会问怎么就解决了,那么我可以告诉你,现在数据库的存储过程修改后添加了字段或者删除了字段,只需要在对应的model类对应修改就行,不在需要想使用EF框架一样还得重新生成实体。不信你试试。接下来我们解决第二个问题。
第二个问题:
现在数据虽然从数据库拿出来了,但是前端只需要一部分字段,且类型不同怎么办?
1、创建一个和前端需要的数据类型一样的model类,当然名字的和数据库对应的model类型区别开。
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Threading.Tasks; 5 6 namespace IBLL.Dto 7 { 8 public class AirportDto 9 { 10 public string Airport_DM { get; set; } 11 public int? Area_DM { get; set; } 12 public string JC { get; set; } 13 public string QC { get; set; } 14 } 15 }
2、数据模型映射到前端需要的模型,这就需要AutoMapper
下载地址:http://pan.baidu.com/s/1c2Knjfa
引用了dll文件之后就需要配置Automapper
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Threading.Tasks; 5 using AutoMapper; 6 using IBLL.Dto; 7 8 9 namespace BLL.AutoMapper 10 { 11 public class AutoMapperConfig 12 { 13 public static void Configure() 14 { 15 Mapper.Initialize(x => 16 { 17 x.CreateMap<double?, string>().ConvertUsing<DoubleToString>();//将数据模型中double?类型全部转化成string 18 x.CreateMap<Entity.Airport, AirportDto>(); 19 20 }); 21 } 22 23 private class DoubleToString : ITypeConverter<double?, string> 24 { 25 public string Convert(double? source, string destination, ResolutionContext context) 26 { 27 return source == null ? "" : source?.ToString("0.00").TrimEnd('0').TrimEnd('.'); 28 } 29 } 30 } 31 }
我这还封装了一下,也一并分享给大家
1 using AutoMapper; 2 using System; 3 using System.Collections; 4 using System.Collections.Generic; 5 using System.Text; 6 using System.Threading.Tasks; 7 8 namespace BLL.AutoMapper 9 { 10 /// <summary> 11 /// AutoMapper扩展帮助类 12 /// </summary> 13 public static class AutoMapperHelper 14 { 15 /// <summary> 16 /// 类型映射 17 /// </summary> 18 public static T MapTo<T>(this object obj) 19 { 20 if (obj == null) return default(T); 21 22 return Mapper.Map<T>(obj); 23 } 24 /// <summary> 25 /// 集合列表类型映射 26 /// </summary> 27 public static List<TDestination> MapToList<TDestination>(this IEnumerable source) 28 { 29 30 return Mapper.Map<List<TDestination>>(source); 31 } 32 33 34 } 35 }
3、规则配置完成,现在就剩最后一步。实现对象的完美转换。
1 using IBLL; 2 using System; 3 using System.Collections.Generic; 4 using System.Text; 5 using System.Threading.Tasks; 6 using AutoMapper; 7 using BLL.AutoMapper; 8 using IBLL.Dto; 9 using Entity.Models; 10 11 namespace BLL 12 { 13 public class BLLAirport : IAirport 14 { 15 //获取所有机场 16 public List<AirportDto> GetALLAirpotsList() 17 { 18 var listAirport = AirportEntity.Db.Fetch<Entity.Airport>("select * from Airports); 19 return listAirport.MapToList<AirportDto>(); 20 21 } 22 } 23 }
至此数据结果已经转换。两个问题也解决。当然项目结构不是完整的,大家应该看得懂的。具体的文件位置可根据自己的项目结构进行调整。
这仅仅是我在项目中遇到时解决的办法,有什么问题或者有其他的办法请大家多多指教。谢谢!