AutoMapper在.Net(asp.net MVC)專案下的應用以及IDataReader轉List說明
AutoMapper在.Net(asp.net MVC)專案下如何配置和應用的呢?我們首先說配置初始化
AutoMapper在.Net(asp.net MVC)專案下的應用
首先在應用啟動時要註冊對映的檔案,直接在Global.asax中的Application_Start類中註冊即可 這裡我們將註冊的具體方法寫在了 AutoMapperUtil.RegisterAutoMapper工具類中:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
//註冊AutoMapper配置
AutoMapperUtil.LoadConfig();
}
工具類如下:
/// <summary>
/// 自動對映工具
/// </summary>
public static class AutoMapperUtil
{
/// <summary>
/// 從配置檔案載入
/// </summary>
/// <param name="sectionName">節點名稱</param>
public static void LoadConfig(string sectionName = "autoMapper")
{
var config = ConfigurationManager.GetSection(sectionName) as NameValueCollection;
if (config != null)
{
var assemlies = config.Keys
.Cast<string>()
.Select(e => config[e])
.Where(e => !string.IsNullOrEmpty(e))
.ToArray();
Mapper.Initialize(cfg => {
//支援datareader to list
cfg.AddDataReaderMapping();
cfg.AddProfiles(assemlies);
});
}
Mapper.AssertConfigurationIsValid();
}
}
這裡要說明下注冊的方式也有多種,AddProfiles有多個過載
最簡單的方式就是通過
Mapper.Initialize(cfg =>
{
cfg.AddProfile<ModelMapperProfile>();
});
public class ModelMapperProfile : Profile
{
CreateMap<Book, BookView>()
}
本人使用的是 void AddProfiles(params Assembly[] assembliesToScan); 這個方式註冊程式集下的Profiles,其原理是註冊程式集後,程式會自動化掃面程式集下所有繼承Profile的類裡的對映資訊進行註冊,程式碼如下:
public static void LoadConfig(string sectionName = "autoMapper")
{
var config = ConfigurationManager.GetSection(sectionName) as NameValueCollection;
if (config != null)
{
var assemlies = config.Keys
.Cast<string>()
.Select(e => config[e])
.Where(e => !string.IsNullOrEmpty(e))
.ToArray();
Mapper.Initialize(cfg => {
cfg.AddProfiles(assemlies);
});
}
Mapper.AssertConfigurationIsValid();
}
配置檔案:
<configSections>
<section name="autoMapper" type="System.Configuration.NameValueSectionHandler, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>
<autoMapper>
<!--鍵為程式集簡稱,可隨意命名,不重複即可,值為程式集名稱-->
<add key="ProxyService" value="CSP.RE.Repository" />
</autoMapper>
這樣我的對映類就可以建立在CSP.RE.Repository下任何位置。
到這裡註冊就完成了,在進行model關係對映時會使用一些通用的幫助類
///協變性:派生程度較大型別分配(賦值)給派生程度較小型別
/// <summary>
/// 對映到目標型別資料
/// </summary>
/// <typeparam name="TMapperType"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static TDestination MapTo<TDestination>(this object value) where TDestination : class
{
if (value == null)
return default(TDestination);
return Mapper.Map<TDestination>(value);
}
/// <summary>
/// 對映到目標型別資料集合
/// </summary>
/// <typeparam name="TDestination">目標型別</typeparam>
/// <param name="values">源型別集合</param>
/// <returns></returns>
public static IEnumerable<TDestination> MapTo<TDestination>(this IEnumerable values) where TDestination : class
{
if (values == null) return new List<TDestination>();
return Mapper.Map<IEnumerable<TDestination>>(values);
}
/// <summary>
/// 將 DataTable 轉為實體物件
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dt"></param>
/// <returns></returns>
public static IEnumerable<TDestination> MapTo<TDestination>(this DataTable dt) where TDestination : class
{
if (dt == null || dt.Rows.Count == 0)
return new List<TDestination>();
return Mapper.Map<IEnumerable<TDestination>>(dt.CreateDataReader());
}
/// <summary>
/// 將 DataSet 轉為實體物件
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="ds"></param>
/// <returns></returns>
public static IEnumerable<TDestination> MapTo<TDestination>(this DataSet ds) where TDestination : class
{
if (ds == null || ds.Tables.Count == 0 || ds.Tables[0].Rows.Count == 0)
return new List<TDestination>();
return Mapper.Map<IEnumerable<TDestination>>(ds.Tables[0].CreateDataReader());
}
這裡就不在多說
IDataReader轉List說明
在專案中我需要將datatable以及dataset轉成List ,查了下資料 automapper官網有獨立的專案支撐其實現AutoMapper.Data,需要在nuget中安裝AutoMapper.Data包
然後註冊的地方有點變化:
public static void LoadConfig(string sectionName = "autoMapper")
{
var config = ConfigurationManager.GetSection(sectionName) as NameValueCollection;
if (config != null)
{
var assemlies = config.Keys
.Cast<string>()
.Select(e => config[e])
.Where(e => !string.IsNullOrEmpty(e))
.ToArray();
Mapper.Initialize(cfg => {
cfg.AddProfiles(assemlies);
});
}
Mapper.AssertConfigurationIsValid();
}
變成:
public static void LoadConfig(string sectionName = "autoMapper")
{
var config = ConfigurationManager.GetSection(sectionName) as NameValueCollection;
if (config != null)
{
var assemlies = config.Keys
.Cast<string>()
.Select(e => config[e])
.Where(e => !string.IsNullOrEmpty(e))
.ToArray();
Mapper.Initialize(cfg => {
//支援datareader to list
cfg.AddDataReaderMapping();
cfg.AddProfiles(assemlies);
});
}
Mapper.AssertConfigurationIsValid();
}
這裡多了一個cfg.AddDataReaderMapping(); 這個就是註冊支援datareader to list的
dome和對映關係註冊:
public class DevicewareDto
{
public string DeviceNumber{ get; set; }
public string SIMCCID { get; set; }
}
Mapper.Initialize(cfg =>
{
cfg.AddDataReaderMapping();
cfg.CreateMap<IDataReader, DevicewareDto>();
});
DataTable dt = new DataTable();
dt.Columns.Add("DeviceNumber", typeof(string));
dt.Columns.Add("SIMCCID", typeof(string));
for (int i = 0; i < 10; i++)
{
var newRow = dt.NewRow();
newRow["DeviceNumber"] = "DeviceNumber";
newRow["SIMCCID"] = "SIMCCID";
dt.Rows.Add(newRow);
}
var list = Mapper.Map<IEnumerable<DevicewareDto>>(dt.CreateDataReader());
----------------------------------------------------------------------------------------------------------
Mapper.Initialize(cfg =>
{
cfg.AddDataReaderMapping();
cfg.CreateMap<IDataReader, DevicewareDto>();
});
Mapper.AssertConfigurationIsValid();
DataSet ds = new DataSet();
DataTable dt = new DataTable();
dt.Columns.Add("DeviceNumber", typeof(string));
dt.Columns.Add("SIMCCID", typeof(string));
for (int i = 0; i < 10; i++)
{
var newRow = dt.NewRow();
newRow["DeviceNumber"] = "DeviceNumber";
newRow["SIMCCID"] = "SIMCCID";
dt.Rows.Add(newRow);
}
ds.Tables.Add(dt);
var list = Mapper.Map<IEnumerable<DevicewareDto>>(ds.CreateDataReader());
但是有兩個問題
註冊對映關係
在控制檯程式中 cfg.CreateMap<IDataReader, DevicewareDto>();加不加這句註冊的程式碼都不會有問題沒問題的,但是在mvc中加了是會報錯的,錯誤提示是從IDataReader到DevicewareDto關係對映時沒有指定FNumber和SIMCCID的對映關係,去掉之後能完成對映且不報錯,這個點感覺很詭異 暫時沒有分析出原因,後續會繼續分享。
同名與不同名屬性之間的對映
目前只能支援類的屬性和列名是相同之間對映 不然是對映不出來值的,看了好多方案還是沒有找到合適的解決方案 即使使用ForMember去指定對映關係(列名)也是不可的 只能轉換出來同名屬性的值, 那就換了種思路去解決,使用DataRow來實現datatable轉List
註冊資訊如下:
CreateMap<DataRow, KnowledgeOverview>()
.ForMember(x => x.Title, opt => opt.MapFrom(src => src["Title"]))
.ForMember(x => x.AbStract, opt => opt.MapFrom(src => src["Summary"]))
.ForMember(x => x.Authors, opt => opt.MapFrom(src => src["Creator"]))
.ForMember(x => x.KeyWords, opt => opt.MapFrom(src => src["KeyWords"]))
.ForMember(x => x.Organizations, opt => opt.MapFrom(src => src["Contributor"]))
.ForMember(x => x.Fund, opt => opt.MapFrom(src => src["Fund"]))
.ForMember(x => x.Source, opt => opt.MapFrom(src => src["Source"]))
.ForMember(x => x.PublishDate, opt => opt.MapFrom(src => src["DATE"]));
這樣就可以實現屬性名和列名不同的值對映 但是也存在一些問題 就是即使是同名列也要使用ForMember()指定對映關係 不然就出不來值,這個大家要注意 !!!
補充說明關於 同名與不同名屬性之間的對映的問題
通過研究官方的issus發現 有網友使用了IDataRecord實現了通過ForMember只要指定不同命屬性就可以完成對映,在控制檯嘗試了一下確實是可以的,程式碼如下:
public class DevicewareDto
{
public string FNumber { get; set; }
public string SIMCCID { get; set; }
}
Mapper.Initialize(cfg =>
{
cfg.AddDataReaderMapping();
cfg.CreateMap<IDataRecord, DevicewareDto>()
.ForMember(dest => dest.FNumber, opt => opt.MapFrom(src => (string)src["DeviceNumber"]));
});
Mapper.AssertConfigurationIsValid();
DataSet ds = new DataSet();
DataTable dt = new DataTable();
dt.Columns.Add("DeviceNumber", typeof(string));
dt.Columns.Add("SIMCCID", typeof(string));
for (int i = 0; i < 10; i++)
{
var newRow = dt.NewRow();
newRow["DeviceNumber"] = "DeviceNumber"+ i;
newRow["SIMCCID"] = "SIMCCID"+ i;
dt.Rows.Add(newRow);
}
ds.Tables.Add(dt);
var list = Mapper.Map<IEnumerable<DevicewareDto>>(ds.CreateDataReader());
//DataTable dt = new DataTable();
//dt.Columns.Add("DeviceNumber", typeof(string));
//dt.Columns.Add("SIMCCID", typeof(string));
//for (int i = 0; i < 10; i++)
//{
// var newRow = dt.NewRow();
// newRow["DeviceNumber"] = "DeviceNumber";
// newRow["SIMCCID"] = "SIMCCID";
// dt.Rows.Add(newRow);
//}
//var list = Mapper.Map<IEnumerable<DevicewareDto>>(dt.CreateDataReader());
以為一切皆大歡喜 結果在MVC中依然無法通過對映關係檢查,不過也斷有了突破
相關文章
- 在ASP.NET Core MVC 2.2 中使用AutoMapperASP.NETMVCAPP
- ASP.NET MVC - PageData的應用ASP.NETMVC
- C#獲取類以及類下的方法(用於Asp.Net MVC)C#ASP.NETMVC
- 在Docker容器中執行ASP.NET MVC應用程式DockerASP.NETMVC
- AutoMapper在ABP框架中的使用說明APP框架
- AspNetCoreRateLimit應用於MVC專案求助NetCoreMITMVC
- 微軟在 Apache 下開源 ASP.NET MVC微軟ApacheASP.NETMVC
- 在 ASP.NET Core 專案中使用 AutoMapper 進行實體對映ASP.NETAPP
- ASP.NET MVC應用程式把文字寫在圖片上ASP.NETMVC
- ASP.NET MVC 應用提速的十種方法ASP.NETMVC
- 建立一個ASP.NET MVC 5專案ASP.NETMVC
- AutoMapper在MVC中的運用小結APPMVC
- ASP.NET的Page.IsPostBack 屬性詳細說明(轉)ASP.NET
- 在ASP.NET MVC應用程式中隨機獲取一個字串ASP.NETMVC隨機字串
- .Net core 中 AutoMapper的應用APP
- ASP.NET MVC在IIS6下部署的小技巧ASP.NETMVC
- Asp.Net Mvc5表單提交之List集合ASP.NETMVC
- MVC專案實踐,在三層架構下實現SportsStore-09,ASP.NET MVC呼叫ASP.NET Web API的查詢服務MVC架構ASP.NETWebAPI
- .Net Mvc AutoMapper簡單使用MVCAPP
- ASP.Net Core 5.0 MVC中AOP思想的體現(五種過濾器)並結合專案案例說明過濾器的用法ASP.NETMVC過濾器
- 專案管理在HIS專案實施中的應用(轉)專案管理
- 【趙勳】在ASP.NET應用程式中上傳檔案ASP.NET
- 專案管理在企業中的應用(轉)專案管理
- IoC在ASP.NET Web API中的應用ASP.NETWebAPI
- ASP.NET Core 入門教程 2、使用ASP.NET Core MVC框架構建Web應用ASP.NETMVC框架架構Web
- ASP.NET + MVC5 入門完整教程三 (上) --- 第一個 MVC 專案_lingshuangcanxue-CSDN 部落格_asp.net mvcASP.NETMVCGC
- ASP.NET MVC 匯入Excel檔案ASP.NETMVCExcel
- ASP.NET檔案下載的實用方法ASP.NET
- ASP.NET MVC與ASP.NET WebFormASP.NETMVCWebORM
- 關於包(Package)應用規範的說明 (轉)Package
- 專案需求說明書
- ASP.NET MVC下的非同步Action的定義和執行原理[轉]ASP.NETMVC非同步
- MVC在WebE的對應 (轉)MVCWeb
- 專案管理在營銷部門的應用(轉)專案管理
- 風險管理在施工專案管理中的應用(轉)專案管理
- 在 Docker 中部署 ASP.NET CORE 應用DockerASP.NET
- Asp.net中多專案共享Session (轉)ASP.NETSession
- asp.net mvc 之旅 —— 第六站 ActionFilter的應用及原始碼分析ASP.NETMVCFilter原始碼