Search code examples
c#entity-framework-6automapper

Injected profile not used in IQueryable.ProjectTo extension method


I have a method which returns IQueryable and in the method it calls the IQueryable.ProjectTo extension method. I am able to map fields with different names from my entity/database objects to the DTO but only when an instance of the configuration mapping is created within the method. However, when I try to inject a profile class with the same configuration mapping through IMapper, the code runs without error but the fields with different names are not mapped i.e. SellCcyRate.

I have looked through the automapper documentation and cannot see where the issue is. Would someone be able to advise?

I am using

  1. AutoMapper v11.0.1
  2. AutoMapper.Extensions.Microsoft.DependencyInjection v11.0.0
  3. EF Core 6

Please find my setup below:

TradeListDtoProfile.cs

    public class TradeListDtoProfile : Profile
    {
        public TradeListDtoProfile()
        {
            CreateMap<Deal, TradeListDto>()
            .ForMember(dest => dest.SellCCYRate, opt => opt.MapFrom(src => src.RateValueFrom));
        }
    }

Startup.cs - ConfigureServices method


public void ConfigureServices(IServiceCollection services) {
    services.AddAutoMapper(typeof(TradeListDtoProfile));
}

Controller.cs

public class TradeController: ControllerBase {
    private readonly EfCoreContext _efCoreContext;
    private readonly IMapper _mapper;

    public TradeController(EfCoreContext efCoreContext, IMapper mapper) {
        _efCoreContext = efCoreContext;
        _mapper = mapper

    }

    public List < TradeListDto > RetrieveTrade() {

        var tradeService = new DisplayTradesService(_efCoreContext);
        return tradeService.FilterSortPage(_mapper);
    }

}

DisplayTradesService.cs

    public class DisplayTradesService
    {
        private readonly EfCoreContext _context;

        public DisplayTradesService(EfCoreContext context)
        {
            _context = context;
        }

        public List<TradeListDto> FilterSortPage(SortFilterPageOptions options, IMapper mapper)
        {
            return _context.Deal
                .AsNoTracking()
                .MapTradeToDto(mapper).ToList();
        }

    }

TradelistDtoSelect.cs


    public static class TradeListDtoSelect
    {
        public static IQueryable<TradeListDto> MapTradeToDto(this IQueryable<Deal> deals, IMapper mapper)
        {
            //var configuration = new MapperConfiguration(cfg => cfg.CreateMap<Deal, TradeListDto>()
            //.ForMember(dest => dest.SellCCYRate, opt => opt.MapFrom(src => src.RateValueFrom)));

            //deals.ProjectTo<TradeListDto>(configuration); // This works

            return deals.ProjectTo<TradeListDto>(mapper.ConfigurationProvider); // This doesn't

        }
    }


Solution

  • You cannot mix attribute mapping with the fluent API for the same map. Remove the attribute from your DTO class.

    It seems that the attribute overwritten your fluent configuration.