【问题标题】:Repository pattern giving exception while updating record更新记录时出现异常的存储库模式
【发布时间】:2014-10-27 12:15:29
【问题描述】:

在我的 MVC 应用程序中,我一直在为 DAL 使用存储库模式。

现在,当我选择一个实体记录并更新实体字段值并执行更新操作时,出现以下错误。

附加“DAL.User”类型的实体失败,因为另一个实体 相同类型的已经具有相同的主键值。这个可以 使用“附加”方法或设置状态时发生 如果图中的任何实体具有,则实体为“未更改”或“已修改” 键值冲突。这可能是因为一些实体是新的并且 尚未收到数据库生成的键值。在这种情况下使用 'Add' 方法或 'Added' 实体状态来跟踪图形和 然后将非新实体的状态设置为“未更改”或“已修改”为 适当的。"} System.Exception

以下是存储库的东西:

public void Update(TEntity entity)
{
    if (_context.Entry(entity).State != EntityState.Modified)
    {
         _dbSet.Attach(entity);
        _context.Entry(entity).State = EntityState.Modified;
    }
}

调用如下: 在 Bussines 图层库中: 经理类:

    private readonly IUnitOfWork _unitOfWork;
    private IRepository <User , int> UserRepository
    {
        get
        {
            return _unitOfWork.GetRepository<AccountUser, int>();
        }
    }
    public void UpdateUserEntity(UserDTO u)
    {
        try
        {

            User model = new User ();
            UserRepository.Update(Mapper.Map(u, model));
            _unitOfWork.SaveChanges();
        }
        catch (Exception ex)
        {
            throw;
        }
    }

请指导我如何解决上述错误。

【问题讨论】:

标签: asp.net-mvc entity-framework repository-pattern data-access-layer


【解决方案1】:

是因为这个原因, “TEntity 实体作为一个新对象而不是已经存在的对象”。 意味着,实体框架将每个新对象视为新条目。(即使具有相同的现有旧数据,PK & all)。

解决办法是,

首先从数据库中检索对象

对同一对象执行/分配更改(最好不更改主键)

然后做状态为 Modified ,Update,SaveChange()

【讨论】:

  • 它已经存在,因为我首先检索然后填充 ui 并且 ui 将更新值,然后调用抛出高于 expceiton 的更新方法。请检查与管理层相关的更新问题。
【解决方案2】:

异常表示已附加具有相同键的另一个实体,但引用不同。

  • 异常可能是由先前附加的实体引起的。

    db.Set<Entity>().Attach(new Entity { Id = 123 });
    db.Set<Entity>().Attach(new Entity { Id = 123 }); // different reference but same key
    
  • 或者也可能是由自动附加的跟踪实体引起的。

    db.Set<Entity>().FirstOrDefault(e => e.Id == 123); // automatically attached
    db.Set<Entity>().Attach(new Entity { Id = 123 }); // different reference but same key
    

第二个原因可以通过在检索项目时提及AsNoTracking来解决。

db.Set<Entity>().AsNoTracking().FirstOrDefault(e => e.Id == 123);

或者为了安全起见,您可以使用此扩展来始终分离任何附加的实体。

public static class DbSetExtension
{
    public static void SafeAttach<T>(
        this DbContext context, 
        T entity, 
        Func<T, object> keyFn) where T : class
    {
        var existing = context.Set<T>().Local
            .FirstOrDefault(x => Equals(keyFn(x), keyFn(entity)));
        if (existing != null)
            context.Entry(existing).State = EntityState.Detached;

        context.Set<T>().Attach(entity);
    }
}

用法。

db.SafeAttach(entity, e => e.Id);

【讨论】:

  • 即使现有实体的状态更改为分离,附加新实体仍会引发错误,您是否有任何评论。
  • AsNoTracking 解决了我的问题。这真是太棒了,我想知道为什么当我从 DBContex 获取它并修改对象然后附加修改后的对象时,它抛出了异常,因为这是我第一次根据我的理解附加该实体。但我错了,不知道实体框架的自我跟踪机制。谢谢!
猜你喜欢
  • 2017-05-17
  • 2011-08-21
  • 2014-06-07
  • 2016-09-19
  • 2017-09-08
  • 2015-07-11
  • 2015-07-15
  • 2017-09-11
  • 1970-01-01
相关资源
最近更新 更多