实体框架+通用存储库+工作单元=>实体已经附加

时间:2014-06-04 20:42:47

标签: asp.net-mvc entity-framework dbcontext unit-of-work

我的Generic Repository的这两种方法都有问题。在我的控制器中,我使用我的工作单元(调用基于通用存储库的存储库)检索当前用户。

 CurrentUser = UtilisateurBuilder.Build(UnitOfWork.UsersRepository.Recuperer(user=>user.MailAddress==WebSecurity.CurrentUserName).First());

上面的代码在我的控制器的构造函数中执行,所以我总是可以访问当前的用户信息。在我的一个动作中,我有一个执行一些更新的代码:

  CurrentUser.Photo = NewPathToPhoto;
  UnitOfWork.UsersRepository.Update(CurrentUser);

但此时我收到以下错误:

  

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

当我调试时,我看到dbSet仍然包含在构造函数控制器中检索的实体。所以我的问题是我如何阅读它,以及这种模式应该如何工作,因为每次需要更新时我都可能在更新之前检索一个对象。

以下是我的通用存储库的相关代码:

public ICollection<TDomain> Recuperer(Expression<Func<TObject, bool>> filter = null,
            Func<IQueryable<TObject>, IOrderedQueryable<TObject>> orderby = null)
        {
            IQueryable<TObject> query = dbSet;

            if (filter != null)
            {
                query = query.Where(filter);
            }


            List<TDomain> objects = new List<TDomain>();
            foreach (TObject o in query)
            {
                objects.Add(Mapper.Map<TObject, TDomain>(o));
            }

            return objects;
        }

    public void Update(TDomain entity)
    {
        TObject o = Mapper.Map<TDomain, TObject>(entity);
        dbSet.Attach(o);
        context.Entry(o).State = EntityState.Modified;
    }

谢谢!

更新:

我忘记了Generic Repository的重要定义:

 this.context = contextInjected;
 dbSet = context.Set<TObject>();

1 个答案:

答案 0 :(得分:1)

我认为最快的解决方法是将Recuperer中的第一行更改为

IQueryable<TObject> query = dbSet.AsNoTracking();

这将阻止对象附加到上下文。

更基本的解决方案是从DbSet.Local集合中查找附加用户,将属性从TDomain entity复制到其中,以便更改跟踪器将修改实体状态本身,更新查询将仅更新修改后的属性。

相关问题