-1

I have this EmployeeEntity class which is part of my database context.

 public class EmployeeEntity
 {
    public int Id { get; set; }
    public string FirstName { get; set; }
    //more properties
 }

And I have an EmployeeModel class:

public class EmployeeModel 
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    //more properties
}

When mapping from model to entity, I ignore the Id so that EF Core can generate it:

cfg.CreateMap<EmployeeModel, EmployeeEntity>().ForMember(dest => dest.Id, opt => opt.Ignore());

This is all working when I add a new employee. However, when I update an existing employee, the DbContext never saves my updates.

Here is how I am updating the database:

var employeeEntity = businessEntity.Employees 
                                   .FirstOrDefault(x => x.Id == employee.Id);   // get employee

// update it using provided employee model 
employeeEntity = _mapper.Map<EmployeeEntity>(employee);

await dbContext.SaveChangesAsync();  

I thought this was because once AutoMapper has mapped the model to entity, EF Core stops tracking it.

But manually modifying employeeEntity state before calling SaveChangesAsync() throws an exception that an employeeentity with this id is already being tracked:

dbContext.Entry(employeeEntity).State = EntityState.Modified;
await dbContext.SaveChangesAsync();  

If I manually map all properties of the model to the entity, the save works fine so it is definitely an issue with how I am using AutoMapper. How can I solve this using AutoMapper?

Thanks

0

2 Answers 2

1

This

// update it using provided employee model 
employeeEntity = _mapper.Map<EmployeeEntity>(employee);

will create brand new object of type EmployeeEntity. So it will not have Id, so you need to do an extra assignment (without Id EF will consider as new entity, if you try to update, EF will complain about lack of Id - because it won't be able to find it):

// update it using provided employee model 
employeeEntity = _mapper.Map<EmployeeEntity>(employee);
employeeEntity.Id = employee.Id;

Now, you have created new entity, but it is not new, so you have to attach it to context in Modified state with:

dbContext.Entry(employeeEntity).State = EntityState.Modified;

Update

If after applying this fix you get error about tracked entity, you need to further investigate the issue. You could start with something like this

var trackedEntity = _context.ChangeTracker.Entries<EmployeeEntity>().FirstOrDefault(x => x.Entity.Id == employee.Id);

Now you can either update found entity, if found, or detach it and attach new one in Modified state.

If tracked entity is null (not found), you can go ahead, and just attach new one in Modified state.

Reference: EF Core 'another instance is already being tracked'

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks but this is what I had tried and it throws the exception that the entity is being tracked already
So you need to get tracked entity and update it instead
Please, see my update :)
1

Use mapping from the source object to the existing destination object.

Like this

var employeeEntity = businessEntity.Employees 
                                   .FirstOrDefault(x => x.Id == employee.Id);

_mapper.Map<EmployeeModel, EmployeeEntity>(employee, employeeEntity);

// Do your work here


// Then
await dbContext.SaveChangesAsync();

You could review the source code on the AutoMapper repo here

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.