更新通用存储库中的实体时出错

时间:2015-07-28 19:33:34

标签: c# asp.net-mvc automapper

我正在构建一个通用存储库,除了更新方法之外,所有其他方法都可以工作。这是代码:

 public void Update(T1 obj)
    {
        T2 item = Mapper.Map<T1, T2>(obj);
        //db.Entry(item).State = EntityState.Modified;
        //db.Set<T2>().Attach(item);
        db.Entry<T2>(item).State = EntityState.Modified;
        db.SaveChanges();

    }

我正在使用AutoMapper将我的商业模式映射到我的实体模型。在我的控制器中,我有以下内容:

        userModel = userIDService.SelectByID(id);
        userModel.Active = false;
        userIDService.Update(userModel);

该模型运行良好,并将Active值作为False。但它给了我以下错误:

Attaching an entity of type 'Data.UserIdentification' failed because 
another entity of the same type already has the same primary key value. 
 This can happen when using the 'Attach' method or setting the state of 
 an entity to 'Unchanged' or 'Modified' if any entities in the graph 
have conflicting key values. This may be because some entities are new 
and have not yet received database-generated key values. In this case 
 use the 'Add' method or the 'Added' entity state to track the graph and 
 then set the state of non-new entities to 'Unchanged' or 'Modified' as 
appropriate.

我该如何解决这个问题?我尝试了几种不成功的方法。 添加了通用回购代码:

public class GenericRepository<T1, T2>:IGenericRepository<T1> 
    where T1 : class
    where T2: class

{
    private Data.Entities db = null;
    private DbSet<T2> table = null;

    public GenericRepository()
    {
        this.db = new Data.Entities();
        table = db.Set<T2>();
    }

    public GenericRepository(Entities db)
    {
        this.db = db;
        table = db.Set<T2>();
    }

    public IQueryable<T1> SelectAll()
    {
        return table.ToList().AsQueryable().Select(x => Mapper.Map<T2, T1>(x));
    }

    public T1 SelectByID(object id)
    {
        return Mapper.Map<T2, T1>(table.Find(id));
    }

    public void Insert(T1 obj)
    {
        T2 item = Mapper.Map<T1, T2>(obj);
        table.Add(item);
    }

    public void Update(T1 obj)
    {
        //T2 item = Mapper.Map<T1, T2>(obj);
        //table.Attach(item);
        //db.Entry<T2>(item).State = EntityState.Modified;
        //db.SaveChanges();
        T2 item = Mapper.Map<T1, T2>(obj);
        db.Set<T2>().Attach(item);
        db.Entry<T2>(item).State = EntityState.Modified;
        db.SaveChanges();




    }

    public void Delete(object id)
    {
        T2 existing = table.Find(id);
        table.Remove(existing);
    }

    public void Save()
    {
        db.SaveChanges();
    }

EDIT2:添加了UserIdentification实体

 public partial class UserIdentification
{
    public System.Guid id { get; set; }
    public System.Guid user_id { get; set; }
    public int id_type { get; set; }
    public System.DateTime expiration_date { get; set; }
    public System.DateTime Created { get; set; }
    public Nullable<bool> Active { get; set; }

    public virtual IdentificationType IdentificationType { get; set; }
    public virtual UserInfo UserInfo { get; set; }
}

编辑3:商业模式

    public Guid id { get; set; }
    public System.Guid user_id { get; set; }
    public int id_type { get; set; }
    public System.DateTime expiration_date { get; set; }
    public System.DateTime Created { get; set; }
    public Nullable<bool> Active { get; set; }
    public virtual IdentificationType IdentificationType { get; set; }

3 个答案:

答案 0 :(得分:5)

如果对检索和更新操作使用相同的DbContext,则在更新时,您的上下文已经跟踪了您的实体(具有此主键的实体)。来自MSDN

  

更改被跟踪实体的状态

     

您可以通过在其条目上设置State属性来更改已被跟踪的实体的状态。例如:

var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" }; 

using (var context = new BloggingContext()) 
{ 
    context.Blogs.Attach(existingBlog); 
    context.Entry(existingBlog).State = EntityState.Unchanged; 

    // Do some more work...  

    context.SaveChanges(); 
}
  

请注意,为已经跟踪的实体调用“添加”或“附加”   也可以用来改变实体状态。例如,打电话   当前处于已添加状态的实体的附加将更改   它的状态为Unchanged。

我认为你错过了Attach电话(你注释掉了)。请尝试

public void Update(T1 obj)
{
    T2 item = Mapper.Map<T1, T2>(obj);
    db.Set<T2>().Attach(item);
    db.Entry<T2>(item).State = EntityState.Modified;
    db.SaveChanges();
}

答案 1 :(得分:3)

我只想离开这里:

https://vimeo.com/131633177

答案 2 :(得分:0)

我有完全相同的问题,所有其他方法(添加,删除,获取)工作正常,更新的例外。 我在dbContext尝试附加实体时收到错误:

    public virtual void Update(T entity)
    {
        dbSet.Attach(entity);
        dataContext.Entry(entity).State = EntityState.Modified;
    }

此存储库方法“studentRepository.Update(student);”从服务层调用。

    public StudentAdapterModel SaveStudent(StudentAdapterModel studentAdapterModel)
    {
        try
        {
            Student student = null;
            if (studentAdapterModel.EventId == 0)
            {
                student = new Student();
                student = Mapper.Map<StudentAdapterModel, Student>(studentAdapterModel);
                studentRepository.Add(student);
            }
            else
            {
                //student = studentRepository.GetById(studentAdapterModel.EventId);
                student = studentRepository.Get(e => e.EventId == studentAdapterModel.EventId);
                try
                {
                    student = Mapper.Map<StudentAdapterModel, Student>(studentAdapterModel);

                }
                catch (Exception ex2)
                {
                    string errMess = ex2.ToString().Trim();
                }

                auctionEventRepository.Update(auctionEvent);

            }
            unitOfWork.Commit();
            studentAdapterModel.EventId = student.EventId;
            return studentAdapterModel;
        }
        catch (Exception ex)
        {
            string errMess = ex.ToString().Trim();
        }
        return null;
    }

但如果我不使用Mapper

,它的工作正常
    //student = studentRepository.GetById(studentAdapterModel.EventId);
            student = studentRepository.Get(e => e.EventId == studentAdapterModel.EventId);
            try
            {
                //student = Mapper.Map<StudentAdapterModel, Student>(studentAdapterModel);
                student.Name = StudentAdapterModel.Name;
            }
            catch (Exception ex2)
            {
                string errMess = ex2.ToString().Trim();
            }