2015-06-09 137 views
3

我使用实体框架在我的Web API应用这样的修改:实体未能与实体框架

[HttpPut] 
    public System.Web.Mvc.JsonResult UpdateAccount(CollaborateurModel item) 
    { 
     if (ModelState.IsValid) 
     { 
      ApplicationUser user = UserManager.FindByIdAsync(item.id_user_fk).Result; 
      user.Roles.Clear(); 
      UserManager.AddToRoleAsync(item.id_user_fk, item.Role); 
      ajt_collaborator entity = Mapper.Map<CollaborateurModel, ajt_collaborator>(item); 
      repo.UpdateCollaborateur(entity); 
      return new System.Web.Mvc.JsonResult { Data = true }; 
     } 
     else 
     { 
      return new System.Web.Mvc.JsonResult { Data = false }; 
     } 
    } 

在BLL

public void UpdateCollaborateur(ajt_collaborator collaborateur) 
     { 
      if (cruder == null) cruder = new Crud<ajt_collaborator>(); 
      cruder.Update(collaborateur); 
     } 

在DAL

public bool Update(params T[] items) 
     { 
      if (context == null) context = GetContext(); 
      try 
      { 
       foreach (T item in items) 
       { 
        context.Entry(item).State = System.Data.Entity.EntityState.Modified; 
       } 
       context.SaveChanges(); 
       return true; 
      } 
      catch 
      { 
       return false; 
      } 
     } 

例外是thr自己在Update方法

失败附加类型的实体“sport.DAL.Entities.ajt_collaborator”的,因为同一类型的另一实体中已经有此主键值。当您使用“附加”方法或将“未更改”值或“已修改”设置为实体的状态时,可能发生这种情况,实体图形是否具有冲突关键值。一些实体可能是新的,可能还没有收到由数据库生成的任何键值。在这种情况下,使用“Add”方法或“Added”实体绘制图形,并将值“Unchanged”或“Modified”分配给除新实体以外的状态实体。

我需要知道

  1. 这是什么异常的原因是什么?
  2. 我该如何解决?
+1

而不是'映射器。Map (item);'你可以在实体上执行'Find',然后使用该对象进行更新? – ramiramilu

+0

@ramiramilu你的意思是找到实体,然后用Collaborate的属性填充它,而不是使用Automapper转换它?这怎么能改变结果呢? –

+1

我想'Mapper.Map'会给你一个新的对象,然后你将'Modified'设置为新的对象。但是已经存在一个具有相同'id'的对象。这就是为什么你会得到这个错误。所以做一个'find',使用'Mapper.Map'这个对象来映射'CollaborateurModel'属性到对象,然后用它来更新。 – ramiramilu

回答

2

,如下图所示不要在ajt_collaborator entity -

ajt_collaborator entity = Mapper.Map<CollaborateurModel, ajt_collaborator>(item); 

而不是使用ajt_collaborator entityFind(或Where等,这样就不会有一个新的对象,但我们可以让现有的对象,它已经填充存在于实体中),然后使用Automapper将所有从item的属性映射到entity。最后使用映射的实体进行更新。

1
  1. EF认为,上下文和数据库是不同步的,因为你是标记项为已修改但它不有其主键设置的值。

  2. 处理这种情况的典型模式是检查PK场,并设置相应的实体状态:

context.Entry(item).State = (item.PK == default(int)) ? System.Data.Entity.EntityState.Added : System.Data.Entity.EntityState.Modified;

(其中默​​认(INT)是你PK的数据类型)

在你的情况下,通过确保PK/key字段甚至被发送到该方法,以便它在自动映射时不会丢失,或者在调用Update之前从数据库中重新提取项目HOD。

1

也可能是您的item未使用主键收到,或者映射后主键可能会丢失。

+0

'CollaborateurModel' id属性与'ajt_collaborator' ID有相同的名称吗?也许你有不正确的自动映射器配置。 – floatas

+0

它是相同的名称,我检查主键是传递给BLL方法,然后它传递给DAL方法 –

+1

以及[MSDN博客](https://msdn.microsoft.com/en-us/data/ jj592676.aspx)你做了一切正确的事情,你可以尝试使用或在设置'state' attach' context.Attach(item);' – floatas