2011-01-10 144 views
0

我一直把头发都撕了这么多天,在我完全秃顶之前,现在是时候让所有的人比我更聪明,怎么做。如何使用实体框架代码优先方法编辑实体?

我使用实体框架4代码首先CTP 5和MVC 3

异常消息,现在是“具有相同键的对象已经存在于ObjectStateManager该ObjectStateManager无法追踪多个对象同一把钥匙“。

一起来这里的编辑表单发送到控制器:

public ActionResult Save(ClientEntity postedClient) 
    { 
     try 
     { 
      if (ModelState.IsValid) 
      { 
       Base.clientInterface.Save(postedClient); 
       return RedirectToAction("Index"); 
      } 
     } 
     catch (Exception) 
     { 

      throw; 
     } 

     SetupManageData(null, postedClient); 
     return View("Manage"); 

    } 

客户端界面上的保存方法是这样的:

public void Save(ClientEntity theClient) 
    { 
     SetContext(); 


     if (theClient.clientId == 0) 
      this.pContext.Clients.Add(theClient); 
     else 
     { 
      ClientEntity existingClient = GetSingle(theClient.clientId); // Get the existing entity from the data store. 

      // PseudoCode: Merge existingClient and theClient - Can this be done without using ObjectStateManager?    
      // PseudoCode: Attach merged entity to context so that SaveChanges will update it in the database - is this correct? 
     } 

     this.pContext.SaveChanges(); 

    } 

    private void SetContext() 
    { 
     if (this.pContext == null) 
      this.pContext = new PersistanceContext();   
    } 

持久化上下文是的DbContext,看起来像这样:

public class PersistanceContext : DbContext 
{ 
    public DbSet<ClientEntity> Clients { get; set; } 
} 

回答

0

clientInterface的生活方式是什么?它是单身还是其他东西可以在多个请求中保持活跃状态​​?

我的猜测是它拥有一个用于在GET请求中获取实体的数据库上下文的实例,当POST尝试(重新)将客户端实体添加到上下文时,旧实例仍然存在他们发生冲突。

尝试使用每个请求销毁clientInterface后面的对象。也许使用支持每个网络请求生活方式的DI容器,因此您不必担心它。

我希望我的猜测是正确的,这是有帮助的。

0

这应该有效。

if (theClient.clientId == 0) 
    { 
     this.pContext.Clients.Add(theClient); 
    } 
    else 
    { 
     ClientEntity existingClient = this.pContext.Clients.Single(o => o.ClientId == theClient.ClientId); 

     // map properties 
     existingClient.Name = theClient.name; 
     // .... 

    } 

    this.pContext.SaveChanges(); 

[编辑]

它更容易(IMHO)到对象的创建编辑&分成2个独立的观点和避免我使用TryUpdateModel属性的映射。

[HttpPost] 
public ViewResult Edit(int clientID, FormCollection collection) 
{ 
    var client = pContext.Clients.SingleOrDefault(o => o.ID == clientID); 

    if(!TryUpdateModel(client, collection)) 
    { 
     ViewBag.UpdateError = "Update Failure"; 
    } 
    else 
    { 
     db.SubmitChanges(); 
    } 

    return View("Details", client); 
} 

[HttpPost] 
public ViewResult Create(FormCollection collection) 
{ 
    var client = new Client(); 

    if(!TryUpdateModel(client, collection)) 
    { 
     ViewBag.UpdateError = "Create Failure"; 
    } 
    else 
    { 
     db.Clients.Add(client); 
     db.SubmitChanges(); 
    } 

    return View("Details", client); 
} 
+0

我真的很想避免必须手动映射属性,否则如果添加新属性会有错误的空间。 – 2011-01-12 08:48:48