Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use ProjectTo with Automapper 8.0 Dependency injection

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<DestinationType>).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<T>(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 configuration to the extension method. How do I do that?

like image 953
Alex Avatar asked Nov 28 '18 22:11

Alex


People also ask

How do I use ProjectTo in AutoMapper?

The . ProjectTo<OrderLineDTO>() will tell AutoMapper's mapping engine to emit a select clause to the IQueryable that will inform entity framework that it only needs to query the Name column of the Item table, same as if you manually projected your IQueryable to an OrderLineDTO with a Select clause.

How do I use AutoMapper in Entity Framework?

To use AutoMapper first install NuGet. Then, install AutoMapper from the package manager console: PM> Install-Package AutoMapper.


1 Answers

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 latter leads to client evaluation and needs Include / ThenInclude (or lazy loading) in order to function properly.

like image 92
Ivan Stoev Avatar answered Sep 18 '22 22:09

Ivan Stoev