基础才是重中之重~AutoMapper为已有目标对象映射

简介:

AutoMapper各位一定不会陌生,大叔之前的文章中也提到过,曾经也写过扩展方法,以方便程序开发人员去使用它,而在最近,大叔在一个API项目里,在一个POST请求由DTO对象为实体对象赋值时,出现了一个问题,使用大叔不得不对原有扩展方法再进行二次的补充。

事情是这样的,有一个DTO对象RequestUserInfo和一个数据库实体对象UserInfo,在进行POST时,将RequestUserInfo对象的值需要赋给UserInfo对象,我们知道DTO对象是根据接口要求从UserInfo里提取的,它的属性要少于UserInfo,这在GET请求时,没有出现任何问题(由userinfo到RequestUserInfo的映射),把对应的属性值赋到了DTO对象上面,百在POST时,由于DTO对象的属性少,所以,UserInfo的某些属性没有被赋到值,出现了Null。

   /// <summary>
    /// DTO 用户-请求参数
    /// 输入参数各属性都是可空的,为空时不去验证,并且查询时不去构造查询条件
    /// </summary>
    public class RequestUserInfo : RequestBase
    {
        public int? Id { get; set; }
        [MaxLength(10, ErrorMessage = "用户名最多为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 = "用户名只能由~50个字符组成")
        public string UserName { get; set; }
        [DisplayName("真实姓名"), Required]//StringLength(30, MinimumLength = 6, ErrorMessage = "真实姓名只能由6~30个字符组成")
        public string RealName { get; set; }
        [DisplayName("密码"), Required]// StringLength(20, MinimumLength = 6, ErrorMessage = "密码由6~20个字符组成")
        public string Password { get; set; }
        [DisplayName("电子邮件"), Required, EmailAddress]
        public string Email { get; set; }
    }

以上是两个对象的内容,在AutoMapper的概念里,在GET请求时,UserInfo相当于TSource源对象,RequestUserInfo相当于TResult目标对象,而在POST请求时,这个正好相反,所以我们之前定义的扩展方法就有问题了,它会将UserInfo里的某些属性变成null,这是正常的,因为在进行AutoMapper时,如果你不给它传目标对象,它会自动构建一个新对象。

扩展之前的方法,它AutoMapper支持为已有目标对象赋值

        /// <summary>
        /// 为已经存在的对象进行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));

        }

这样在程序调用时,会把已经存在的对象result以参数的形式传入,如下代码

   public void Update(RequestUserInfo request)
        {
            var entity = userRepository.GetModel().FirstOrDefault(i => i.Id == request.Id);
            request.MapTo<UserInfo>(entity);
            userRepository.Update(entity);
        }

这时entity是从数据库里拿出来的完整数据,再把它的DTO属性进行自动映射赋值,最后把赋值后的对象进行更新!

上面是EF,LINQ这些ORM工具里的通用作法,即先拿出对象,再为指定属性赋新的值,最后提交到数据库!

感谢您的阅读!

本文转自博客园张占岭(仓储大叔)的博客,原文链接:基础才是重中之重~AutoMapper为已有目标对象映射,如需转载请自行联系原博主。

目录
相关文章
|
4月前
|
安全 C# 开发者
C#中的默认接口方法:接口演化的新篇章
【1月更文挑战第11天】本文探讨了C# 8.0中引入的默认接口方法,这一特性允许在接口中定义具有默认实现的方法。文章介绍了默认接口方法的语法、使用场景,以及它们如何影响接口的设计和实现,同时讨论了默认接口方法带来的好处和潜在的陷阱。
|
2月前
|
Java
java面向对象高级分层实例_实体类
java面向对象高级分层实例_实体类
12 1
|
2月前
|
Java 数据库
java面向对象高级分层实例_数据库操作类
java面向对象高级分层实例_数据库操作类
12 1
|
7月前
|
设计模式 Java 数据库连接
JAVA设计模式8:装饰模式,动态地将责任附加到对象上,扩展对象的功能
JAVA设计模式8:装饰模式,动态地将责任附加到对象上,扩展对象的功能
|
12月前
|
Java
java面向对象高级分层实例_接口类
java面向对象高级分层实例_接口类
45 0
|
安全 C# 索引
C#编程基础——类
C#编程基础——类
C#编程基础——类
|
设计模式 缓存 关系型数据库
浅入ABP 系列(7):对象映射
浅入ABP 系列(7):对象映射
260 0
|
Java 容器
JavaWeb中四大域对象的作用范围
JavaWeb中四大域对象的作用范围
218 0
|
数据库
【自然框架 NatureFW】里的两种“映射”方式
   自然框架里面采用了两种映射关系,一个是流行的ORM,另一是非主流的“CCM ” (我自己想的,呵呵)。   先说一下ORM。ORM是O和R的映射关系。也看到很多人写关于ORM的文章,发现好像有个误区。
923 0
|
SQL 监控 索引
AutoMapper自动映射
十年河东,十年河西,莫欺少年穷。 学无止境,精益求精。 不扯犊子,直接进入正题: AutoMapper自动映射常用于EF中,能很好的解决DTO和Model之间相互映射的问题。在未使用AutoMapper之前,我们回顾下传统的对象相互映射的方法。
2062 0