Automapper Optimization3 min read

Today I’ll write about Automapper optimization when using Entity Framework.

I won’t go into too much detail about what AutoMapper is and how to use it, I’ll give you just a short intro. 

I will focus more on how to optimize AutoMapper if you are using Entity Framework. As I see some people tend to use it in a wrong way which might cause your application poor performance.

What is AutoMapper?

If you don’t know what Automapper is, it’s a library which helps to map one object to another.

It’s used i.e., when converting from domain objects to data transfer objects. 

So this makes our life easier when we want to convert from one object to another. 

With only a few lines of code using Automapper we can get rid of tedious work converting between the objects.

But in order for Automapper to be aware of our classes we need to set-up AutoMapper configuration.

In one of my future Youtube videos, I will show you how to do it in the DotNet Core project, but in short, it’s used like this:

var config = new MapperConfiguration(cfg => cfg.CreateMap<DomainObject, DomainObjectDto>());

This way we did one way mapping. In order to map vice verse we just add .ReverseMap() function, i.e.:

var config = new MapperConfiguration(cfg => cfg.CreateMap<DomainObject, DomainObjectDto>().ReverseMap());

So how do we use AutoMapper?

Simple as this:

var mapper = config.CreateMapper();
// or
var mapper = new Mapper(config);
DomainObjectDto dtoObject = mapper.Map<DomainObjectDto>(domainObject); // where domainObject is instantiated object which needs to be mapped to dto

Ok, this is just a short intro. Let’s get to the real stuff.

THE PROBLEM

Let’s imagine we have some code like this one by using repository pattern:

// i.e.: Cars Repository function
public async Task<IEnumerable<CarDto>> GetCarsAsync() {
return await _context.Cars.ToListAsync();
}

and in our WebAPI controller we have something like this:

// Cars Controller function
public async Task<ActionResult<IEnumerable<CarDto>>> GetCars() {
var cars = await carsRepository.GetCarsAsync();
var carsDto = _mapper.Map<IEnumerable<CarDto>>(cars);
return Ok(carsDto);
}

As you can see, we are calling the EF, which goes to our DB and returns our cars collection.

This car’s collection is stored inside our memory and ONLY THEN we map our DB results (which is in memory) to our DTO objects.

THE SOLUTION

If you are thinking about getting all the stuff we need during our SQL query(like getting only the properties we need), you would be pretty damn right!

But we don’t want to map objects manually, don’t we? 

Why not? Cause we are laaaaazy and there is no point in doing that, especially, when using AutoMapper!

Ok, so how do we do it by using AutoMapper?

Well, we will be adding a new function to our repository like this one:

// i.e.: Cars Repository optimized function
public async Task<IEnumerable<CarDto>> GetCarsOptimizedQueryAsync() {
return await _context.Cars.ProjectTo<CarDto>(_mapper.Configuration).ToListAsync(); // _mapper is an object we inject into Repository constructor so we can access all AutoMapper functions and props
}

And then we refactor our WebAPI controller function like this:

// Cars Controller refactored function
public async Task<ActionResult<IEnumerable<CarDto>>> GetCars() {
var cars = await carsRepository.GetCarsOptimizedQueryAsync();
return Ok(carsDto);
}

So obviously, by using the AutoMapper function ProjectTo<>, we do the querying and mapping during the DB execution, that way we retrieve already filtered results and there is no need to map objects in memory.

Oh, by the way, in case you are using Include (Entity Framework function when complex objects are used), there is no need for that anymore. As AutoMapper & EF does all this for us automatically.

As always, automate everything you can and write less code as it is much better!

Cheers

(Visited 112 times, 1 visits today)

Leave a comment

Your email address will not be published. Required fields are marked *