【问题标题】:Repository pattern Generic Write Repository issue - Object State Manager Issue存储库模式通用写入存储库问题 - 对象状态管理器问题
【发布时间】:2016-10-05 02:06:47
【问题描述】:

我正在使用存储库模式做一个 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();
 }

任何想法我该如何解决这个问题?

【问题讨论】:

  • @HenkHolterman 我在这条线上遇到错误 _context.Entry(item).State = entityState;我是否应该将其分配给 var model = _TenantServices.GetItemById(Guid.Parse(id)); ?
  • @HenkHolterman 问题出在我的 Tenant Repository 类上,正如你所说,我发布的代码没有任何问题。

标签: c# asp.net-mvc entity-framework repository-pattern asp.net-mvc-5


【解决方案1】:

每当您从数据库中检索对象时,Entity Framework 都会立即开始跟踪(附加)该对象。您将能够对检索到的对象进行更改(即设置属性值)并调用SaveChanges(),以便在数据库中更新对象,而无需设置EntityState

事实上,如果你尝试Attach 或设置一个已经被跟踪的对象的EntityState,你会得到上面提到的错误。

因此,要解决该错误,您可以:

  • 使用TContext 的一个实例进行检索,并使用另一个实例进行更新。在这种情况下,您应该在更新方法中附加并设置 EntityState 以使更改持久化。
  • 使用TContext 的单个实例来检索和更新,但不要再尝试Attach 或设置EntityState。设置属性值后直接调用SaveChanges
  • 使用TContext 的单个实例,但在检索记录时,您可以调用AsNoTracking()。这将允许您在更新期间安全地Attach 或设置EntityState

希望对您有所帮助。

【讨论】:

  • 我在项目中有多个上下文,这会是个问题吗?我正在检索数据 asnotracking 但它似乎也没有太大影响
  • 即使您只有一个继承自 DbContext 的类,您所描述的问题也可能发生。即使你有多个上下文类,我相信只有一个上下文类可以容纳你的租户DbSet(请确认?)。
  • 是的,只有一个 dbcontext
  • 查看我正在使用 AsNotracking 但仍然没有运气的编辑
猜你喜欢
  • 1970-01-01
  • 2014-09-19
  • 2015-01-22
  • 1970-01-01
  • 1970-01-01
  • 2014-07-27
  • 1970-01-01
  • 2013-11-26
  • 1970-01-01
相关资源
最近更新 更多