如何使用Entity Framework Code First方法编辑实体?

时间:2011-01-10 18:26:45

标签: entity-framework-4 ef-code-first

我已经把头发撕成了几天,在我完全秃顶之前,是时候问所有比我更聪明的人如何做到这一点。

我正在使用Entity Framework 4和Code First 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");

    }

客户端界面上的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();           
    }

Persistance上下文是DBContext,如下所示:

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

2 个答案:

答案 0 :(得分: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();

[编辑]

更容易(恕我直言)分割创作&amp;将对象编辑为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); 
}

答案 1 :(得分:0)

clientInterface的生活方式是什么?它是一个单独的东西还是让它在多个请求中保持活着的东西?

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

尝试使用每个请求销毁clientInterface后面的对象。也许使用支持per-webrequest生活方式的DI容器,这样你就不用担心了。

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