EF Core with Automapper throw Exception ‘Entity type cannot be tracked’

There are a couple of misconceptions here

  1. Bare in mind that a DTO is a dumb class, in a sense that it does nothing but serving as a container for the information to travel in a strongly typed way. You will be normally dealing with DTOs when the front-end send you some data and your backend catches on the controller parameter (I know this is not exactly true, just trying to make a point here), or when returning a DTO to the front end to whatever reason it needs. The general approach then will be:

  2. Frontend sent a DTO

  3. Backend controller catches

  4. Backend services map the DTO to some domain model of interest (automapper)

  5. Backend services perform the logical steps of the business rules such as saving a record on the database or updating something I don’t know you name it

  6. Backend service map the response (if any) to a DTO (automapper)

  7. Backend controller sends the data right back to the front end, to do whatever it needs to do

Now, regarding your bug it’s a common bug of entity frameworks begginers. Let me ilustrate what happend:

UserDTO userDTO = this._UserBLL.GetUser("Unit", "Test"); 
//tip: as per the explanation above this should't be a DTO

//EF says "alright!, programmer pull out
//a record from the database and got a object of type UserDTO with Id = "someguid"
//im gonna begin tracking this object to see if it changes in the
//execution of the code.
//In case my fellow programmer wants to modify this object and 
//save it in on the database, as I was tracking it down in 
//the first place, I'm gonna know how to build my
//SQL statements to perform the right update/delete/create sentence in 
//SQL form.

Somewhere over the mapping you are creating the same object type with the same Id and then entity framework go bananas

//EF says: "mmm, that's weird, im tracking the same object 
//again, im gonna alert the human. *throws exception*

The key here is to re-read the documentation of entity framework/core to fully understand how entity framework think Now, regarding your code and business requirement, you should be aiming to do something like this:

//Suppose that the in the controller parameter we receive this DTO
var newUserDto = new UserDto() 
{
    Firstname = "Rodrigo",
    Lastname = "Ramirez",
    CreatedBy = 1, //this can be the user Id of the user that sent this DTO
};

var userToCreate = Mapper.Map<User>(newUserDto);
var userCreator = UserRepository.GetById(newUserDto.CreatedBy);
userToCreate.CreatedBy = userCreator;

final words on this topic:

  1. It’s a matter of preferences but I do rather read
var user = Mapper.Map<User>(newUserDto); //hey mapper, be a pal and transform this newUserDto into a User object.
  1. Check that you are using List<> to map when you don’t need to.
  2. For this business logic, you don’t need to prevent entity framework to begin tracking a given entity. But in case you find such case you can checkout the method “AsNoTracking()” that does that.
  3. Review the necesity of create a new GUID over User class instantiation. This seems to be buggy and you need to fully understand how EF works in order to succed with this practice.
  4. The thing you want to do is a common audit practice, and it’s advisable that you override the method OnSaveChanges() to perform this task.

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top