1

私はこれについて何日も髪を引き裂いてきましたが、完全にハゲになる前に、私より賢いすべての人にこれを行う方法を尋ねる時が来ました.

Code First CTP 5 および MVC 3 で Entity Framework 4 を使用しています。

現在の例外メッセージは、「同じキーを持つオブジェクトが既に 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");

    }

クライアント インターフェイスの Save メソッドは次のとおりです。

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

2 に答える 2

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

[編集]

オブジェクトの作成と編集を2つの別々のビューに分割し、TryUpdateModelを使用するプロパティのマッピングを回避する方が簡単です(IMHO)。

[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); 
}
于 2011-01-10T22:00:05.527 に答える
0

clientInterface のライフスタイルとは?それはシングルトンですか、それとも複数のリクエストでそれを維持するものですか?

私の推測では、GET 要求でエンティティを取得するために使用されたデータベース コンテキストのライブ インスタンスを保持し、POST がクライアント エンティティをコンテキストに (再) 追加しようとすると、古いエンティティがまだ存在し、競合するということです。

すべてのリクエストで clientInterface の背後にあるオブジェクトを破棄してみてください。Web リクエストごとのライフスタイルをサポートする DI コンテナーを使用すると、心配する必要がなくなります。

私の推測が正しかったことを願っています。

于 2011-01-16T13:13:41.787 に答える