Dapper + Slapper.AutoMapper 一對多映射實作及BUG註記
【天啊!Slapper.AutoMapper自己腦補幫我寫完了程式,是在哈囉?】
前言
- Slapper非常吃重命名規則,而且會以底線Underline作為資料分支的重要指標,
所以原資料表欄位命名若有出現底線,則必須全部取代掉。 - 欄位名稱中必須有「ID」這個字眼,當作分層的主鍵(亦可另外指定主鍵)
基本介紹
開發環境
- Microsoft Visual Studio .NET 2017 Professional
- Dapper v2.0.30
- Slapper.AutoMapper v1.0.0.9
參考資料
取得方式
- Nuget
已知須注意的狀況
- Oracle最大欄位命名長度為30,在Slapper.AutoMapper層數愈多,名稱愈長是確定的。
所以在一開始的時候,自己的「命名規則」就顯得特別重要! - 若Model的層數太深,Slapper.AutoMapper的效能會有斷崖式的落差。
所以多層數的Model,要適時拆開成多組,再組合起來會比較好。
我自己測試的狀況是… 6-7層要50000ms,拆開來跑的話,怎麼跑也不超過100ms。
實作
MODEL
/// <summary>
/// 事業群
/// </summary>
public class MyGroupModel
{
/// <summary>
/// 事業群ID
/// </summary>
public int ID { get; set; }
/// <summary>
/// 管轄處
/// </summary>
public List<DIV> DIV { get; set; }
}
/// <summary>
/// 處
/// </summary>
public class DIV
{
/// <summary>
/// 處ID
/// </summary>
public int ID { get; set; }
/// <summary>
/// 處級名稱
/// </summary>
public int NAME { get; set; }
/// <summary>
/// 管轄部門
/// </summary>
public List<DEPT> DEPT { get; set; }
}
/// <summary>
/// 部門
/// </summary>
public class DEPT
{
/// <summary>
/// 部門ID
/// </summary>
public int ID { get; set; }
/// <summary>
/// 部門名稱
/// </summary>
public int NAME { get; set; }
}
PROGRAM
public List<MyGroupModel> getGroupModel(string GroupID, string DeptID)
{
DynamicParameters parameter = new DynamicParameters();
DataProviderBase db = new OracleDataProvider(connectionString);
parameter = new DynamicParameters();
string select_cmd = @"
SELECT MYGROUP.GROUP_ID ID
, MYDIV.DIVISION_ID DIV_ID
, MYDIV.DIVISION_NAME DIV_NAME
, MYDEPT.DEPTARTMENT_ID DIV_DEPT_ID
, MYDEPT.DEPTARTMENT_NAME DIV_DEPT_NAME
FROM ORADB.MYGROUP MYGROUP /*人事-事業群檔*/
LEFT JOIN ORADB.MYDIVISION MYDIV /*人事-處檔*/
ON MYGROUP.GROUP_ID = MYDIV.MYDIV_GROUPID
LEFT JOIN ORADB.MYDEPARTMENT MYDEPT /*人事-部門檔*/
ON MYDIV.MYDIV_ID = MYDEPT.MYDEPT_DIVID
WHERE MYGROUP.GROUP_ID = :GroupID
AND MYDEPT.DEPTARTMENT_ID = :DeptID
";
parameter.Add(":GroupID", GroupID);
parameter.Add(":DeptID", DeptID);
db = new OracleDataProvider(connectionString);
//此處為使用 Dapper取回資料
var p2M = db.GetDataModel<dynamic>(select_cmd, CommandType.Text, parameter);
//此處透過Slapper.AutoMapper將資料填成model的資料結構
var ss = (Slapper.AutoMapper.MapDynamic<MyGroupModel>(p2M)).ToList();
return ss;
}
後記
(關於這個部份,有網友回覆提醒我原因了,特別感謝Kevin,我將查詢的結果寫在最後了,記得要看哦!!)
Slapper.AutoMapper「好像」有個BUG,
會說好像是因為,也許它也是「Auto」的一個部份???
請看下面兩段程式,第一層的ID一樣,它就自動幫我組合了。
我是省下了一個組合的功夫...
但…這真的是我們需要的結果嗎?
/// <summary>
/// 查詢IT&HR的組織
/// </summary>
/// <returns></returns>
public List<MyGroupModel> getITnHRModel_1(string GroupID)
{
List<MyGroupModel> ITModel = new List<MyGroupModel>();
List<MyGroupModel> HRModel = new List<MyGroupModel>();
ITModel = getGroupModel(GroupID, "IT");
HRModel = getGroupModel(GroupID, "HR");
//還沒組合IT&HR Model
//HRModel就已經被Slapper組合完了???
return HRModel;
}
/// <summary>
/// 查詢IT&HR的組織
/// </summary>
/// <returns></returns>
public List<MyGroupModel> getITnHRModel_2(string GroupID)
{
List<MyGroupModel> result = new List<MyGroupModel>();
getGroupModel(GroupID, "IT");
result = getGroupModel(GroupID, "HR");
//result又被Slapper組合起來了???
return result;
}
2020/05/05更新:
經網友Kevin提醒,原來是我忽略了keepCache參數,而造成的影響。
/// <summary>
/// Converts a dynamic object to a type <typeparamref name="T"/>.
///
/// Population of complex nested child properties is supported by underscoring "_" into the
/// nested child properties in the property name.
/// </summary>
/// <typeparam name="T">Type to instantiate and automap to</typeparam>
/// <param name="dynamicObject">Dynamic list of property names and values</param>
/// <param name="keepCache">If false, clears instance cache after mapping is completed. Defaults to true, meaning instances are kept between calls.</param>
/// <returns>The type <typeparamref name="T"/></returns>
/// <exception cref="ArgumentException">Exception that is thrown when the <paramref name="dynamicObject"/> cannot be converted to an IDictionary of type string and object.</exception>
public static T MapDynamic<T>( object dynamicObject, bool keepCache = true)
{
return (T)MapDynamic(typeof(T), dynamicObject, keepCache);
}
針對keepCache的描述翻譯就是:若是false,會在執行之後清除Cache。預設為true,表示會在保留前次結果。
所以呢,不是一個bug,而是Slapper.Automapper,真的很自作主張方便。真的可以節省一 些時間。 給個讚!!
Written By Felix Hsieh