How to use ProjectTo with Automapper 8.0 Dependency injection

automapper entity-framework-core

Question

I'm using Automapper's (8.0) DI pattern in my project and am looking to start using ProjectTo in my Entity Framework Core entity queries.

Here is an example of what I have managed to get to work:

    public async Task<IEnumerable<SomeViewModel>> GetStuffAsync() {

        return await _dbContext.SomeEntity
            .ProjectTo<SomeViewModel>(_mapper.ConfigurationProvider)
            .ToListAsync();
    }

The above call returns all the expected records but it requires both injecting IMapper in the constructor of the repository as well as a Using reference to AutoMapper.QueryableExtensions.

There are two versions of the AutoMapper docs that I have found and they seem to provide conflicting info.

These docs https://automapperdocs.readthedocs.io/en/latest/Dependency-injection.html state the following:

Using DI is effectively mutually exclusive with using the IQueryable.ProjectTo extension method. Use IEnumerable.Select(_mapper.Map).ToList() instead.

And these docs http://docs.automapper.org/en/stable/Dependency-injection.html state this:

Starting with 8.0 you can use IMapper.ProjectTo. For older versions you need to pass the configuration to the extension method IQueryable.ProjectTo(IConfigurationProvider).

Following the first documentation's example, I converted my query to this:

    public IEnumerable<SomeViewModel> GetStuff() {

        return _dbContext.SomeEntity
            .Select(_mapper.Map<SomeViewModel>)
            .ToList();
    }

However, that method returns 0 records (the previous returned everything) and the method needed to be converted from Async to synchronous as ToListAsync() wasn't supported by the extended Select. Clearly I'm missing something. Also, I'm not sure if that is the correct technique as the second set of docs talk about using IMapper.ProjectTo for version 8.0 without passing the configuaration to the extension method. How do I do that?

1
9
11/28/2018 10:19:54 PM

Accepted Answer

Starting with 8.0 you can use IMapper.ProjectTo

This means that now IMapper interface has a method ProjectTo (similar to Map). So while you still need injecting IMapper (but you need it anyway if you were using Map, so no difference), you don't need QueryableExtensions and ProjectTo extension method - you simply use the interface method (similar to Map):

return await _mapper.ProjectTo<SomeViewModel>(dbContext.SomeEntity)
    .ToListAsync();

Please note that there is fundamental difference between _mapper.ProjectTo and Select(_mapper.Map) - the former is translated to SQL and executed server side, while the later leads to client evaluation and needs Include / ThenInclude (or lazy loading) in order to function properly.

21
11/29/2018 4:45:23 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow