简体   繁体   English

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

[英]Error Updating Entity in a Generic Repository

I am building a Generic Repository and all other methods work with the exception of the update one. 我正在构建一个通用存储库,除了更新之外,所有其他方法都可以工作。 This is the code: 这是代码:

 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();

    }

I am using AutoMapper to map my business model to my Entity Model. 我正在使用AutoMapper将我的业务模型映射到我的实体模型。 In my controller I have the following: 在我的控制器中,我有以下内容:

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

The model works perfectly and it comes through with the Active value as False. 该模型运行良好,并将Active值作为False。 Yet it gives me the following error: 但它给了我以下错误:

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.

How can I fix this? 我怎样才能解决这个问题? I've tried several methods to no success. 我尝试过几种方法都没有成功。 Added Generic Repo Code: 添加了通用回购代码:

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: Added UserIdentification Entity 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; }
}

EDIT 3: Business Model 编辑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; }

If you use the same DbContext for both retrieve and update operations, then your context already tracks your entity (entity with this primary key) when you update. 如果对检索和更新操作使用相同的DbContext ,则在更新时,上下文已跟踪您的实体(具有此主键的实体)。 From MSDN : 来自MSDN

Changing the state of a tracked entity 更改被跟踪实体的状态

You can change the state of an entity that is already being tracked by setting the State property on its entry. 您可以通过在其条目上设置State属性来更改已被跟踪的实体的状态。 For example: 例如:

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(); 
}

Note that calling Add or Attach for an entity that is already tracked can also be used to change the entity state. 请注意,为已跟踪的实体调用“添加”或“附加”也可用于更改实体状态。 For example, calling Attach for an entity that is currently in the Added state will change its state to Unchanged. 例如,为当前处于已添加状态的实体调用Attach将将其状态更改为Unchanged。

I think you are missing the Attach call (that you commented out). 我认为你错过了Attach调用(你注释掉了)。 Please try 请试试

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();
}

I'm just going to leave this here: 我只想把它留在这里:

https://vimeo.com/131633177 https://vimeo.com/131633177

I have the exact same problem, all other methods (Add, Delete, Get) are working fine a exception of the update. 我有完全相同的问题,所有其他方法(添加,删除,获取)工作正常,更新的例外。 I get the error when the dbContext is trying to attach the entity: 我在dbContext尝试附加实体时收到错误:

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

This repository method "studentRepository.Update(student);" 此存储库方法“studentRepository.Update(student);” is called from the service layer. 从服务层调用。

    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;
    }

But it worked fine if I don't use Mapper 但如果我不使用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();
            }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM