基礎才是重(zhong)中之重(zhong)~AutoMapper為已有(you)目標對象映射
AutoMapper各位一定不(bu)(bu)會陌生,大(da)(da)(da)叔之(zhi)前(qian)的文章中也(ye)提到過(guo),曾經也(ye)寫過(guo)擴展方(fang)法,以方(fang)便程序開發人員(yuan)去使(shi)用它,而在(zai)最近(jin),大(da)(da)(da)叔在(zai)一個(ge)API項目里,在(zai)一個(ge)POST請求由(you)DTO對象(xiang)為實(shi)體對象(xiang)賦值時,出現(xian)了(le)一個(ge)問題,使(shi)用大(da)(da)(da)叔不(bu)(bu)得不(bu)(bu)對原有擴展方(fang)法再進行二(er)次的補充。
事情是(shi)這樣的(de)(de),有(you)一個(ge)DTO對(dui)象RequestUserInfo和一個(ge)數據(ju)(ju)庫實體對(dui)象UserInfo,在(zai)進行POST時,將RequestUserInfo對(dui)象的(de)(de)值需(xu)要賦(fu)給UserInfo對(dui)象,我們知道DTO對(dui)象是(shi)根據(ju)(ju)接口(kou)要求從UserInfo里(li)提取(qu)的(de)(de),它的(de)(de)屬(shu)性(xing)要少于UserInfo,這在(zai)GET請(qing)求時,沒有(you)出現任(ren)何問題(由userinfo到(dao)RequestUserInfo的(de)(de)映射),把對(dui)應的(de)(de)屬(shu)性(xing)值賦(fu)到(dao)了DTO對(dui)象上面,百在(zai)POST時,由于DTO對(dui)象的(de)(de)屬(shu)性(xing)少,所以(yi),UserInfo的(de)(de)某(mou)些屬(shu)性(xing)沒有(you)被(bei)賦(fu)到(dao)值,出現了Null。
/// <summary> /// DTO 用戶-請求參數(shu) /// 輸(shu)入(ru)參數(shu)各屬性都是可空的,為空時(shi)不(bu)去驗證,并且查詢時(shi)不(bu)去構造(zao)查詢條件 /// </summary> public class RequestUserInfo : RequestBase { public int? Id { get; set; } [MaxLength(10, ErrorMessage = "用(yong)戶名最(zui)多為(wei)10個字符")] public string UserName { get; set; } [EmailAddress(ErrorMessage = "Email地址不是合法的")] public string Email { get; set; } [MaxLength(20, ErrorMessage = "用戶名最多為20個字符")] public string RealName { get; set; } }
public class UserInfo : Entity { [DisplayName("用戶名"), Required]// StringLength(50, MinimumLength = 4, ErrorMessage = "用戶名只能(neng)由~50個字符組成") public string UserName { get; set; } [DisplayName("真實姓(xing)名(ming)"), Required]//StringLength(30, MinimumLength = 6, ErrorMessage = "真實姓名只能由6~30個字符(fu)組成") public string RealName { get; set; } [DisplayName("密碼"), Required]// StringLength(20, MinimumLength = 6, ErrorMessage = "密碼由(you)6~20個字(zi)符組成") public string Password { get; set; } [DisplayName("電(dian)子郵件"), Required, EmailAddress] public string Email { get; set; } }
以上是兩個對象的內容,在AutoMapper的概念里,在GET請求時,UserInfo相當于TSource源對象,RequestUserInfo相當于TResult目標對象,而在POST請求時,這個正好相反,所以我們之前定義的擴展方法就有問題了,它會將UserInfo里的某些屬性變成null,這是正常的,因為在進行AutoMapper時,如果你不給它傳目標對象,它會自動構建一個新對象。
擴(kuo)展之前的方法(fa),它AutoMapper支持為(wei)已有目(mu)標對象賦值
/// <summary> /// 為(wei)已經存(cun)在的對象進行automapper /// </summary> /// <typeparam name="TSource"></typeparam> /// <typeparam name="TResult"></typeparam> /// <param name="self"></param> /// <param name="result"></param> /// <returns></returns> public static TResult MapTo<TResult>(this object self, TResult result) { if (self == null) throw new ArgumentNullException(); Mapper.CreateMap(self.GetType().UnderlyingSystemType, typeof(TResult)); return (TResult)Mapper.Map(self, result, self.GetType(), typeof(TResult)); }
這樣在程序調用(yong)時,會(hui)把已經存在的(de)對象(xiang)result以參(can)數的(de)形式傳入,如下代碼(ma)
public void Update(RequestUserInfo request) { var entity = userRepository.GetModel().FirstOrDefault(i => i.Id == request.Id); request.MapTo<UserInfo>(entity); userRepository.Update(entity); }
這時entity是從數(shu)據(ju)庫里拿出(chu)來的完整數(shu)據(ju),再把(ba)它的DTO屬性進行自動映射賦值,最后把(ba)賦值后的對象進行更(geng)新!
上(shang)面是EF,LINQ這些ORM工具里的(de)通(tong)用作法,即先拿出對(dui)象,再為指定屬性(xing)賦新的(de)值,最后(hou)提交到數據庫!
感謝您的閱讀!