2017年5月31日 星期三

[Applied]簡易的資料對映轉換套件



Applied是一個用於處理DTO屬性值對映複製的.NET元件

概念來自於T-SQL的CROSS APPLY,所以擴充函式才會使用Lambda型態的參數做設計


Nuget網址: https://www.nuget.org/packages/Applied/


使用上非常簡單,首先宣告示範程式用的資料物件類別
    public enum UserEnum
    {
        None,
        User
    }
    [Serializable]
    public class User
    {
        public int UserID { get; set; }
        public string Name { get; set; }
        public DateTime? Time { get; set; }
        public UserEnum Enum { get; set; }
    }
    [Serializable]
    public class UserViewModel
    {
        public int UserID { get; set; }
        public string Name { get; set; }
        public DateTime? Time { get; set; }
        public UserEnum Enum { get; set; }
    }
然後建立一個陣列並對其使用Applied提供的擴充函式
    User[] users = new User[]
    {
        new User() { UserID = 1, Name = "Sam     " },
        new User() { UserID = 2, Name = "John    " }
    };

    users.Apply(a => new { Time = DateTime.Now, Enum = UserEnum.User });
    users.Trim();

這裡Apply()會令陣列的所有項目屬性與參數中給的賦值物件的屬性值設為一樣

只要兩者的屬性名稱相同,型別相同或型別能相互轉換的

Trim()則會除去所有字串屬性值的前後空白

因為函式其實有回傳自身所以也能夠使用類似裝飾者的寫法或者用於Linq查詢語法內
    users.Apply(a => new { Time = DateTime.Now, Enum = UserEnum.User }).Trim();
對於一般方式來說此行的程式則大約需要寫成這樣
    for (int i = 0; i < users.Length; i++)
    {
        users[i].Time = DateTime.Now;
        users[i].Enum = UserEnum.User;
        if (users[i].Name != null)
        {
            users[i].Name = users[i].Name.Trim();
        }
    }
如果每個物件需要設定的屬性越多型別轉換越多寫起來就會越麻煩複雜


而且除了有設定好資料類別的資料物件可以使用這些函式以外

DataTable,DataRow,IDictionary(Key為string)等型態的物件也可以使用這些函式設定或作為賦值的參數

另外還有幾個相互轉換用的函式
    UserViewModel[] vm1 = users.ToDataEnumerable<User, UserViewModel>().ToArray();
    DataTable dt1 = users.ToDataTable();
    Dictionary<string, object>[] ds1 = users.ToDictionaries().ToArray();

    UserViewModel[] vm2 = dt1.ToDataEnumerable<UserViewModel>().ToArray();
    UserViewModel[] vm3 = ds1.ToDataEnumerable<UserViewModel>().ToArray();

    DataTable dt2 = vm1.ToDataTable();
    DataTable dt3 = ds1.ToDataTable();

    Dictionary<string, object>[] ds2 = vm1.ToDictionaries().ToArray();
    Dictionary<string, object>[] ds3 = dt1.ToDictionaries().ToArray();


資料類別陣列,DataTable,Dictionary陣列皆可互相轉換


然後是有關效能的部分

Applied的對映功能主要是以TypeDescriptor的方式來達成
沒有需要程式先預初始化的設計,所以是每次呼叫都會自動的做一次Mapping動作
不過其中還是具有依靠陣列長度來判斷是否轉換為使用Expression Tree以加速處理的機制
(Expression Tree初始較慢執行較快,效益臨界值是訂672,以Array或List使用才能判斷)
固每次任務皆少筆數的話整體效能大致上應該不高,不過差別大概也感覺不到(筆數少)
就看請求任務的總次數多或不多來評估適不適合使用了



新版改以Expression Tree為主,在沒有需要程式先預初始化的設計情況

第一次自動Mapping後存取屬性的Lambda會存入記憶體的字典中下次呼叫就能以類別來快取
https://dotblogs.com.tw/initials/2016/08/20/231753

與這篇文章相同的百萬筆測試,結果為700~800左右,原生的14~17倍

結果為400~500,原生的10倍左右


以上請參考,若有錯誤煩請告知,感謝~