Home > Software engineering >  How Can I Map Select With AutoMapper
How Can I Map Select With AutoMapper

Time:12-16

I use AutoMapper to mapping. I needed to use Distinct & Select. But now my mapping is not working and says "Missing type map configuration or unsupported mapping"

What can i do?

        cfg.CreateMap<SearchHistory, SearchDashBoardDto>();

        var searchList = _unitOfWork.SearchRepository.GetSearchHistory(userId, sessionId)
                                .Select(x => new { x.SearchText, x.Url })
                                .Distinct();

        return _mapper.Map<List<SearchDashBoardDto>>(searchList);

CodePudding user response:

You are trying to map an anonymous type to a DTO. Older versions of Automapper would support this via options to attempt to resolve unknown mappings but that gradually got phased out. I believe there is still support for DynamicMap() which should work /w Dmitriy's answer.

Automapper can manage this entirely using ProjectTo. You will need to provide it a MapperConfiguration with how to translate a SearchHistory into a SearchDashBoardDto, and ensure that your search repository is returning IQueryable<SearchHistory> rather than something like IEnumerable<SearchHistory>.

Assuming your DTO has a SearchText and Url column with the same naming convention as the Entity, an example with a local configuration:

var config = new MapperConfiguration(cfg => cfg.CreateMap<SearchHistory, SearchDashBoardDto>());

var searchList = _unitOfWork.SearchRepository
    .GetSearchHistory(userId, sessionId)
    .ProjectTo<SearchDashBoardDto>(config)
    .Distinct()
    .ToList();

The mapper configuration is needed for the ProjectTo extension method. This can be configured centrally and passed in as a dependency, or constructed on demand or via a factory method. (I typically place them as static methods on the View Models)

Edit: Alternatively, if you are going through the trouble of using Select to an anonymous type, you may as well just populate your ViewModel:

var searchList = _unitOfWork.SearchRepository.GetSearchHistory(userId, sessionId)
    .Select(x => new SearchDashBoardDto
    { 
        SearchText = x.SearchText, 
        Url = x.Url 
    }).Distinct()
    .ToList();

If your repository is returning IEnumerable<SearchHistory> or the like this won't work, and it certainly won't be ideal from a performance perspective as it would be returning the entire search history entities. (Where you only care about 2 fields, and distinct results) The above can help build more efficient queries to let the DB call return just the data you want to return. If the repository is returning IEnumerable or IList etc. rather than IQueryable, then my recommendation would be either to move this across to using IQueryable or get rid of the repository all-together and just use the DbContext/DbSets.

CodePudding user response:

This should work.

_unitOfWork.SearchRepository.GetSearchHistory(userId, sessionId)
                                .Select(x => new { x.SearchText, x.Url })
                                .Distinct()
                                .Select(s => _mapper.Map<SearchDashBoardDto>(s))
                                .ToList()
  • Related