Reputation: 3406
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
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
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
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
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