2011-01-10 118 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