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

标签 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 将我的业务模型映射到我的实体模型。在我的 Controller 中,我有以下内容:

        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.

我该如何解决这个问题?我尝试了几种方法都没有成功。 添加了通用 repo 代码:

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

最佳答案

如果您对检索和更新操作使用相同的 DbContext,那么在您更新时,您的上下文已经跟踪了您的实体(具有此主键的实体)。来自 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. 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 调用(您已注释掉)。请尝试

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

关于c# - 更新通用存储库中的实体时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31685516/

相关文章:

c# - Windows 8.1 统一项目中的 Automapper 启动异常

c# - 返回 HelpText 类而不是字符串会意外地起作用

javascript - 如何将复选框的值传递给 MVC5 中的 ActionResult?

asp.net - 有什么理由我不应该自动修剪 html 表单参数吗?

html - 无法将控件添加到我的 ASP 页面中的现有 DIV 元素

c# - 按子元素排序

c# - 如何使用 AutoMapper 深度克隆包含 IList 属性的对象

c# - 为什么来自 Entity Framework 的 SQL 查询在探查器中不可见?

c# - .NET 服务器如何将文件处理结果推送到客户端 jQuery?

c# - 从 C# .NET 中的 DataTable 到 JSON