AutoMapper ограничивает глубину отображения или карта лениво

AutoMapper великолепен, экономит много времени, но когда я начал смотреть на производительность моего приложения, AutoMapper оказался ответственным за потерю производительности.

Я использую отложенную загрузку с NHibernate. В большинстве случаев требуется родительская сущность без необходимости доступа к дочерним сущностям. На самом деле происходит то, что AutoMapper пытается сопоставить как можно больше отношений, в результате чего NHibernate лениво загружает все дочерние объекты (я вижу, что SELECT N + 1 происходит все время).

Есть ли способ ограничить глубину AutoMapper или AutoMapper может лениво отображать дочерние объекты?


person Daniil Harik    schedule 10.08.2010    source источник
comment
У меня точно такая же проблема. Хороший вопрос, для AutoMapper существует множество настроек, поэтому настройка потребуется.   -  person zidane    schedule 12.05.2011


Ответы (3)


Вы можете использовать метод игнорирования для ассоциаций, которые вам не нужно загружать.

Mapper.CreateMap<User, UserDto>()
    .ForMember(dest => dest.LazyCollection, opt => opt.Ignore())
    .ForMember(dest => dest.AnotherLazyCollection, opt => opt.Ignore())
Mapper.CreateMap<UserProperty, UserPropertyDto>()
    .ForMember(dest => dest.PropertyLazyReference, opt => opt.Ignore());
return Mapper.Map<User, UserDto>(user);

Для ассоциаций, которые, как вы знаете, вам понадобятся в вашем dto, вам следует изучить способы более эффективного получения их с помощью начального запроса, но это совершенно новая проблема.

person Sam    schedule 11.08.2010
comment
В итоге я использовал настраиваемые резолверы, спасибо за ваше предложение - person Daniil Harik; 11.08.2010
comment
В недавнем выпуске AutoMapper v2 есть ограничитель .MaxDepth (int), но я не уверен, подходит ли это только для рекурсивных структур объектов или может применяться только к глубоким структурам. - person David Keaveny; 20.12.2011

Возможно, вам стоит рассмотреть возможность использования двух разных dtos; один включает дочерние сущности, а другой - нет. Затем вы можете вернуть правильный dto из вашего уровня обслуживания в зависимости от контекста.

person DanP    schedule 10.08.2010

Я использую предварительные условия, чтобы предотвратить отображение данных.

CreateMap<Team, TeamDto>()
    .ForMember(dto => dto.Users, options =>
    {
        options.PreCondition(ctx => !ctx.Items.ContainsKey(AutoMapperItemKeys.SKIP_TEAM_USERS));
        options.MapFrom(t => t.TeamUsers.Where(tu => tu.IsDeleted == false));
    })
    .ReverseMap();

Когда вызывается Map (), я загружаю словарь Items ключами пропуска для свойств, которые не хочу отображать.

this.mapper.Map<IEnumerable<Team>, IEnumerable<TeamDto>>(teams, opts =>
{
    opts.Items.Add(AutoMapperItemKeys.SKIP_TEAM_USERS, true);
});

Преимущества:

  • вы можете уточнить, какие свойства не отображать
  • предотвращает глубокое сопоставление с вложенными объектами
  • нет необходимости в дублировании dto
  • нет повторяющихся картографических профилей
person Guido Neele    schedule 21.11.2018