【问题标题】:Using Automapper to populate a list in an entity class from a DTO property使用 Automapper 从 DTO 属性填充实体类中的列表
【发布时间】:2021-02-12 20:22:03
【问题描述】:

我对使用 AutoMapper 非常陌生,我花了几天时间在谷歌上搜索解决方案,但没有成功。我正在尝试将如下所示的 DTO 映射到我的实体类,其中包含多个级别的信息(年、季度、季节、期间、周、日)。

这是我的 DTO:

public class CalendarDto
{
    public int Year { get; set; }
    public int Quarter { get; set; }
    public string Season { get; set; }
    public int DayOfWeek { get; set; }
    public string Date { get; set; }
    public int WeekOfYear { get; set; }
    public int DayOfYear { get; set; }
    public int WeekOfPeriod { get; set; }
}

这是我的实体的前两个级别:

    public class Calendar : ICalendar<string>
    {
        public string Id { get; set; }
        public int Year { get; set; }
        public string Date { get; set; }
        public CalendarQuarter Quarters { get; set; }
    }

   public class CalendarQuarter
    {
        public int Year { get; set; }
        public int Quarter { get; set; }
        public string Date { get; set; }
        public List<CalendarSeason> Seasons { get; set; }
    }

如您所见,我从一年到季度、到季节、到时期、到每周和每天都有额外的嵌套级别。我只提供第一个级别,逐季逐年提供,因为我确信一旦我确定了一个级别,其余的将是直截了当的。

我尝试将配置文件设置为从 DTO 分别映射每个类,如下所示,因为所有属性值都匹配。

public class CalendarProfile : Profile
{
    public CalendarProfile()
    {
        CreateMap<CalendarDto, Calendar>().ReverseMap();
        CreateMap<CalendarDto, CalendarQuarter>().ReverseMap();
        CreateMap<CalendarDto, CalendarSeason>().ReverseMap();
        CreateMap<CalendarDto, CalendarPeriod>().ReverseMap();
        CreateMap<CalendarDto, CalendarWeek>().ReverseMap();
        CreateMap<CalendarDto, CalendarDay>().ReverseMap();
    }
}

当我尝试将 DTO 映射到处理程序中的实体时,仅映射了 Calendar 类并且 CalendarQuarters 列表为空。我的理解是配置文件与配置相同,并且在配置文件中创建的所有映射都将在执行 Map 时执行。显然,我错了,我的映射设置不正确,或者两者兼而有之!哈哈

var calendar = _mapper.Map<CalendarDto, Calendar>(parms.Dto);

任何建议将不胜感激。感谢您的帮助!

【问题讨论】:

  • 永远不要以这种方式使用 automaper。 automaper 的一位作者表示,automaper 旨在从实体映射到 DTO 或 VM。从不从 DTO 到实体。您应该使用构造函数或任何设计模式,例如工厂。以这种方式使用 automaper 会在项目长大后给您带来很多问题。

标签: c# automapper


【解决方案1】:

首先要提一下,使用 automapper 可以使映射看起来更容易,但是无法调试代码,并且当您的项目变得很大并且映射不是那么复杂时,您可能会遇到问题(您总是可以显式映射并轻松调试)这很无聊,所以在决定使用它之前最好记住这一点,阅读这篇文章: article1, article2.

如果使用自动映射器,您应该阅读documentation。我认为你需要这样的东西:

CreateMap<Calendar, CalendarDto>().ForMember(dest => dest.Quarters.Quarter, 
                                             opt => opt.Quarter)
                                  .ForMember(dest => dest.Quarters.Quarter.Seasons.Season
                                             opt => opt.Season);

我删除了反向映射,因为我从我的项目中复制了这个并更改了属性,我希望你可以应用到所有属性。当然,您有许多属性,因此您可以链接 ForMember 并定义所有映射,如果您不这样做,则此映射器仅映射具有相同名称的属性。

【讨论】:

  • 永远不要在大型​​商业项目中使用 automaper。这将是不可维护的,尤其是当 DTO 与实体的结构不同时。
  • 好的,我看到了评论,但你能详细说明一下吗?我和同事一起上大学,我们成功地完成了项目,我们有很多实体和许多 DTO。这里的不同之处在于,在这种情况下,实体有很多层次,但我认为这不是大问题。
  • 因为您的项目持续了 1 年。我希望你永远不要尝试调试基于 automaper 的 10 年应用程序;)。 rogerjohansson.blog/2013/12/01/…有很多文章。 cezarypiatek.github.io/post/why-i-dont-use-automapper
  • 所以问题是在实践中它变得非常丑陋并且不可维护?还有什么适合回答?
  • 最好创建某种工厂方法或工厂类。然后您可以调用 var product = _factory.CreateProduct(productsDto); automaper 的开发速度非常快,但维护起来非常糟糕。很难编写单元测试。当您的业务逻辑在 automaper 配置而不是业务服务中编码时,这是非常糟糕的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-02-19
  • 1970-01-01
  • 1970-01-01
  • 2013-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多