Automapper — как применить конфигурацию ForMember на глубоком уровне

#c# #model #automapper #viewmodel #object-object-mapping

#c# #Модель #automapper #viewmodel #объект-сопоставление объектов

Вопрос:

Я пытаюсь изучить asp.NETCore 2.2. Я пытаюсь настроить простой одностраничный сайт. Я столкнулся с проблемой с Automapper, когда ручное отображение с использованием ForMember() работает на верхнем уровне CreateMap<Listing, ListingSearchResultsDto>().ForMember(ListingPhotosUrl) , но не на более низком уровне. У меня есть другое сопоставление CreateMap<User, UserDetailsDto>() , в котором user содержится объект Mylistings типа Listing . Mylistings корректно автоматически сопоставляется ListingSearchResultsDto , но ручная настройка CreateMap<Listing, ListingSearchResultsDto>().ForMember(ListingPhotosUrl) не применяется.

Я пробовал CreateMap<User, UserDetailsDto>().Formember(dest.Mylistings.ListingPhotosUrl,src.Mylistings.Photos.Url) , но, похоже, это невозможно.

Я также пробовал это -> Но не повезло

             var config = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<User, UserDetailsDto>();
                cfg.CreateMap<Listing, ListingSearchResultsDto>()
                .ForMember(dest => dest.ListingPhotosUrl, opt =>
            {
                opt.MapFrom(src => src.Photos.FirstOrDefault(p => p.IsMain).Url);
            });

            });

            var mapper = config.CreateMapper();
  

Код:

AutoMappperProfiles

  public AutoMapperProfiles()
        {
            CreateMap<Listing, ListingSearchResultsDto>()
            .ForMember(dest => dest.ListingPhotosUrl, opt =>
            {
                opt.MapFrom(src => src.Photos.FirstOrDefault(p => p.IsMain).Url);
            });           


            CreateMap<User, UserDetailsDto>();

            CreateMap<ListingPhoto, ListingPhotosDetailedDto>();
        }
  

Пользователь

     public class User
    {
        public int Id { get; set; }
        public string Username { get; set; }

        public ICollection<Listing> MyListings { get; set; }
    }
  

UserDetailsDto

 public class UserDetailsDto
    {
        public int Id { get; set; }
        public string Username { get; set; }

        public ICollection<ListingSearchResultsDto> MyListings { get; set;}
     }
  

Листинг

         public int id { get; set; }
        public string Category { get; set; }
        public string Title { get; set; }

        public ICollection<ListingPhoto> Photos { get; set; }
  

ListingSearchResultsDto

     public class ListingSearchResultsDto
    {
        public int id { get; set; }
        public string Title { get; set; }
        public string ListingPhotosUrl { get; set; }                    
    }
  

Я использую CreateMap<Listing, ListingSearchResultsDto>().Formember(des,src) для ручного сопоставления целевого свойства ListingPhotosUrl . У меня есть другое сопоставление CreateMap<User, UserDetailsDto>() . Внутри User amp; UsedetailsDto classes у меня есть объекты, вызываемые MyListings типами ICollection<Listing> и ICollection<ListingSearchResultsDto> соответственно. MyListings объект автоматически отображается правильно, но ListingPhotosUrl ручное отображение не применяется. CreateMap<Listing,ListingSearchResultsDto>.Formember(des,src)) ручное сопоставление работает на верхнем уровне, но не на более глубоком уровне внутри CreateMap<User, UserDetailsDto>() , можно ли это исправить? Спасибо

Комментарии:

1. Правильно ли настроен DI? Проверьте документы .

Ответ №1:

ИСПРАВЛЕНО — Automapper работал нормально. Проблема в Entity Framework DbContext. Я не включил фотографии в качестве связанных данных в метод ядра EF для загрузки пользовательских данных GETUSER() . Он работал с основным методом EF для загрузки списка GetListing() , потому что у меня было включение для фотографий Include(p => p.Photos) .

После добавления .ThenInclude(p => p.Photos) GetUser() фотографии были возвращены с пользовательскими данными, и automapper успешно сопоставил пользовательские данные, и ListingPhotosUrl было успешно применено ручное сопоставление.

Ядро Entity Framework DbContext:

 public async Task<User> GetUser(int id)
{
    var user = await _context.Users
        .Include(a => a.Avatar)
        .Include(l => l.MyListings)
            .ThenInclude(p => p.Photos)
                .FirstOrDefaultAsync(u => u.Id == id);

    return user;
}

public async Task<Listing> GetListing(int id)
{
    var listing = await _context.Listings
        .Include(p => p.Photos)
        .FirstOrDefaultAsync(l => l.id == id);

    return listing;
}