存储库模式通用写入存储库问题 - 对象状态管理器问题
Repository pattern Generic Write Repository issue - Object State Manager Issue
我正在做一个使用存储库模式的 MVC 项目,我有一个核心写入存储库,如下所示
public abstract class WriteRepository<TContext> : IWriteRepository
where TContext : DbContext, new()
{
private readonly TContext _context;
protected TContext Context { get { return _context; } }
protected WriteRepository()
{
_context = new TContext();
}
public TItem Update<TItem>(TItem item, bool saveImmediately = true) where TItem : class, new()
{
return PerformAction(item, EntityState.Modified, saveImmediately);
}
public TItem Delete<TItem>(TItem item, bool saveImmediately = true) where TItem : class, new()
{
return PerformAction(item, EntityState.Deleted, saveImmediately);
}
public TItem Insert<TItem>(TItem item, bool saveImmediately = true) where TItem : class, new()
{
return PerformAction(item, EntityState.Added, saveImmediately);
}
public void Save()
{
_context.SaveChanges();
}
protected virtual TItem PerformAction<TItem>(TItem item, EntityState entityState, bool saveImmediately = true) where TItem : class, new()
{
_context.Entry(item).State = entityState;
if (saveImmediately)
{
_context.SaveChanges();
}
return item;
}
public void Dispose()
{
_context.Dispose();
}
}
我想用一个操作方法更新我的数据库中的单个字段,在我可以像下面这样更新该值之前我正在做一个 get all
public ActionResult UpdateTenant(string id)
{
Tenant model = new Tenant();
model = _TenantServices.GetItemById(Guid.Parse(id));
model.IsLoginEnabled = true;
_TenantServices.Update(model);
return RedirectToAction("ViewDetails", new { id = model.TenantId });
}
当我这样做时,我收到一条错误消息:“ObjectStateManager 中已存在具有相同键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象。”
我正在使用 AsNoTracking 检索数据,如下所示
public Tenant GetItemById(Guid id)
{
return Context.Tenants.AsNoTracking().Where(t => t.TenantId == id).FirstOrDefault();
}
知道如何解决这个问题吗?
无论何时从数据库中检索对象,Entity Framework 都会立即开始跟踪(附加)该对象。您将能够更改检索到的对象(即设置 属性 值)并调用 SaveChanges()
,以便在数据库中更新对象,而无需设置 EntityState
.
事实上,如果您尝试 Attach
或设置已跟踪对象的 EntityState
,您将收到上述错误。
因此,要解决该错误,您可以:
- 使用您的
TContext
的一个实例进行检索,并使用另一个实例进行更新。在这种情况下,您应该在更新方法中附加并设置 EntityState
以使更改持久化。
- 使用
TContext
的单个实例来检索和更新,但不要再尝试 Attach
或设置 EntityState
。设置 属性 值后直接调用 SaveChanges
。
- 使用
TContext
的单个实例,但在检索记录时可以调用 AsNoTracking()
。这将允许您在更新期间安全地 Attach
或设置 EntityState
。
希望对您有所帮助。
我正在做一个使用存储库模式的 MVC 项目,我有一个核心写入存储库,如下所示
public abstract class WriteRepository<TContext> : IWriteRepository
where TContext : DbContext, new()
{
private readonly TContext _context;
protected TContext Context { get { return _context; } }
protected WriteRepository()
{
_context = new TContext();
}
public TItem Update<TItem>(TItem item, bool saveImmediately = true) where TItem : class, new()
{
return PerformAction(item, EntityState.Modified, saveImmediately);
}
public TItem Delete<TItem>(TItem item, bool saveImmediately = true) where TItem : class, new()
{
return PerformAction(item, EntityState.Deleted, saveImmediately);
}
public TItem Insert<TItem>(TItem item, bool saveImmediately = true) where TItem : class, new()
{
return PerformAction(item, EntityState.Added, saveImmediately);
}
public void Save()
{
_context.SaveChanges();
}
protected virtual TItem PerformAction<TItem>(TItem item, EntityState entityState, bool saveImmediately = true) where TItem : class, new()
{
_context.Entry(item).State = entityState;
if (saveImmediately)
{
_context.SaveChanges();
}
return item;
}
public void Dispose()
{
_context.Dispose();
}
}
我想用一个操作方法更新我的数据库中的单个字段,在我可以像下面这样更新该值之前我正在做一个 get all
public ActionResult UpdateTenant(string id)
{
Tenant model = new Tenant();
model = _TenantServices.GetItemById(Guid.Parse(id));
model.IsLoginEnabled = true;
_TenantServices.Update(model);
return RedirectToAction("ViewDetails", new { id = model.TenantId });
}
当我这样做时,我收到一条错误消息:“ObjectStateManager 中已存在具有相同键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象。”
我正在使用 AsNoTracking 检索数据,如下所示
public Tenant GetItemById(Guid id)
{
return Context.Tenants.AsNoTracking().Where(t => t.TenantId == id).FirstOrDefault();
}
知道如何解决这个问题吗?
无论何时从数据库中检索对象,Entity Framework 都会立即开始跟踪(附加)该对象。您将能够更改检索到的对象(即设置 属性 值)并调用 SaveChanges()
,以便在数据库中更新对象,而无需设置 EntityState
.
事实上,如果您尝试 Attach
或设置已跟踪对象的 EntityState
,您将收到上述错误。
因此,要解决该错误,您可以:
- 使用您的
TContext
的一个实例进行检索,并使用另一个实例进行更新。在这种情况下,您应该在更新方法中附加并设置EntityState
以使更改持久化。 - 使用
TContext
的单个实例来检索和更新,但不要再尝试Attach
或设置EntityState
。设置 属性 值后直接调用SaveChanges
。 - 使用
TContext
的单个实例,但在检索记录时可以调用AsNoTracking()
。这将允许您在更新期间安全地Attach
或设置EntityState
。
希望对您有所帮助。