Aishwarya Shiva
Aishwarya Shiva

Reputation: 3406

Entity not updating using Code-First approach

I have this class that I use for DB operations:

public class EntityService<TEntity> : IRepository<TEntity> where TEntity : BaseModel
{

     ApplicationDbContext _context;
     private DbSet<TEntity> _entities;

     public EntityService()
     {
         _context = new ApplicationDbContext();
     }

     public virtual void Update(TEntity entity)
     {
          if (entity == null)
               throw new ArgumentNullException(nameof(entity));

          try
          {
                var dbEnt = _context.Set<TEntity>().Where(c => c.Id == entity.Id).First();

                dbEnt = entity;
                dbEnt.UpdatedBy = GetCurrentUser();
                dbEnt.DateUpdated = DateTime.Now;
                _context.SaveChanges();
           }
           catch (DbUpdateException exception)
           {
                throw new Exception(GetFullErrorTextAndRollbackEntityChanges(exception), exception);
           }

           //-----other methods for insert and get working fine----
}

There are also other methods in this class for insert and get are working fine. Only this update method is not updating the entity and not throwing the exception.

UPDATE

I am facing similar problem but opposite in functioning here: Add() method adding duplicate rows for linked models in Code-First Entity Framework

I think these two have same reason of Change Tracking. But one is adding other is not updating.

Upvotes: 1

Views: 981

Answers (4)

Aishwarya Shiva
Aishwarya Shiva

Reputation: 3406

Thank you everyone. I received a lots of hint from your answers. As @GertArnold and @Colonel Software's answer hinted me I modified my code like this and it worked:

//Assigning BaseModel properties
entity.CreatedBy = dbEnt.CreatedBy;
entity.UpdatedBy = GetCurrentUser();
entity.DateUpdated = DateTime.Now;
entity.DateCreated = dbEnt.DateCreated;

//Changing entity states
_context.Entry(dbEnt).State = EntityState.Detached;
_context.Entry(entity).State = EntityState.Modified;

_context.SaveChanges();

Upvotes: -1

Azhar Khorasany
Azhar Khorasany

Reputation: 2709

If you have found your entity via Id

var dbEnt = _context.Set<TEntity>().Where(c => c.Id == entity.Id).First();

then why this line?

dbEnt = entity;

Remove the above line as it will remove the reference to the tracked object.

Upvotes: 0

Colonel Software
Colonel Software

Reputation: 1440

After getting entity from _context, update all fields from new detail and set entity state to modified

var dbEnt = _context.Set<TEntity>().Where(c => c.Id == entity.Id).First();
dbEnt.Name = entity.Name;
...
...
...
dbEnt.UpdatedBy = GetCurrentUser();
dbEnt.DateUpdated = DateTime.Now;
_context.Entry(dbEnt).State = EntityState.Modified;
_context.SaveChanges();

Upvotes: 1

Gert Arnold
Gert Arnold

Reputation: 109080

The line...

var dbEnt = _context.Set<TEntity>().Where(c => c.Id == entity.Id).First();

...attaches an entity object to the context and returns a reference to this entity.

Then the line...

dbEnt = entity;

...replaces this reference by a reference to the entity variable that enters the method. That is not the tracked entity object. You basically lost the reference to the tracked entity and it's impossible to change it any longer.

You should either attach entity to the context and mark it as modified, or get dbEnt as you already do and modify and save that object. Both methods have pros and cons, see here.

Upvotes: 4

Related Questions