实体不使用代码优先方法更新
Entity not updating using Code-First approach
我有这个 class 用于数据库操作:
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----
}
此 class 中还有其他方法 insert
和 get
工作正常。只有这个更新方法不更新实体并且不抛出异常。
更新
我遇到了类似的问题,但在这里的功能相反:
我认为这两个更改跟踪的原因相同。但是一个是添加另一个不是更新。
线...
var dbEnt = _context.Set<TEntity>().Where(c => c.Id == entity.Id).First();
...将实体对象附加到上下文和 returns 对此实体的引用。
然后行...
dbEnt = entity;
...将此引用替换为对进入方法的 entity
变量的引用。那是不是被跟踪的实体对象。您基本上丢失了对被跟踪实体的引用,并且无法再更改它。
您应该将 entity
附加到上下文并将其标记为已修改,或者像您已经做的那样获取 dbEnt
并修改并保存 that 对象.两种方法各有利弊,见here.
从 _context 获取实体后,更新新详细信息的所有字段并将实体状态设置为已修改
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();
如果您通过 Id 找到了您的实体
var dbEnt = _context.Set<TEntity>().Where(c => c.Id == entity.Id).First();
那为什么是这一行?
dbEnt = entity;
删除上面的行,因为它会删除对跟踪对象的引用。
谢谢大家。我从你的回答中得到了很多提示。
作为@GertArnold 和
@Colonel Software 的回答暗示我,我像这样修改了我的代码并且它起作用了:
//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();
我有这个 class 用于数据库操作:
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----
}
此 class 中还有其他方法 insert
和 get
工作正常。只有这个更新方法不更新实体并且不抛出异常。
更新
我遇到了类似的问题,但在这里的功能相反:
我认为这两个更改跟踪的原因相同。但是一个是添加另一个不是更新。
线...
var dbEnt = _context.Set<TEntity>().Where(c => c.Id == entity.Id).First();
...将实体对象附加到上下文和 returns 对此实体的引用。
然后行...
dbEnt = entity;
...将此引用替换为对进入方法的 entity
变量的引用。那是不是被跟踪的实体对象。您基本上丢失了对被跟踪实体的引用,并且无法再更改它。
您应该将 entity
附加到上下文并将其标记为已修改,或者像您已经做的那样获取 dbEnt
并修改并保存 that 对象.两种方法各有利弊,见here.
从 _context 获取实体后,更新新详细信息的所有字段并将实体状态设置为已修改
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();
如果您通过 Id 找到了您的实体
var dbEnt = _context.Set<TEntity>().Where(c => c.Id == entity.Id).First();
那为什么是这一行?
dbEnt = entity;
删除上面的行,因为它会删除对跟踪对象的引用。
谢谢大家。我从你的回答中得到了很多提示。 作为@GertArnold 和 @Colonel Software 的回答暗示我,我像这样修改了我的代码并且它起作用了:
//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();