ASP.NET MVC的实体框架

时间:2009-05-21 22:26:32

标签: c# .net asp.net asp.net-mvc entity-framework

如何将强类型控制器与EntityObjects一起使用?

我的失败......

首先我尝试了这个:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model)
{
    db.SaveChanges();
    return RedirectToAction("Index");
}

这实际上无法保存对数据库的任何更改。所以,我试图将模型附加到我的ObjectContext:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model)
{
    db.Attach(Model);
    db.SaveChanges();
    return RedirectToAction("Index");
}

此操作失败,因为“具有空EntityKey值的对象无法附加到对象上下文”。所以,我试图分配EntityKey:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model)
{
    Model.EntityKey = (from Department d in db.Department
                       where d.Id == id
                       select d).FirstOrDefault().EntityKey;
    db.Attach(Model);
    db.SaveChanges();
    return RedirectToAction("Index");
}

这失败了,因为“ObjectStateManager中已存在具有相同键的对象.ObjectStateManager无法使用相同的键跟踪多个对象。”

这应该如何运作?

4 个答案:

答案 0 :(得分:3)

问题是,你所拥有的输入并不是一个完整的模型对象,它具有更改的属性 - 它只是一个新的“开始”,具有你想要在现有实体上覆盖的所有属性。您不发布任何ID属性

这看起来有点冗长,但它是我发现的最好的,所以我在我的项目中做到这一点(调整到你的班级名字,不管失去的东西......):

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model)
{
    var dbDepartment = (from Department d in db.Department
                        where d.Id == id
                        select d).FirstOrDefault() as Department

    dbDepartment.Name = Model.Name;
    dbDepartment.Color = Model.Color;
    // etc, assigning values manually...

    try
    {
        db.SaveChanges();
    }
    catch (Exception ex)
    {
        // oops...
    }
    return RedirectToAction("Index");
}

答案 1 :(得分:1)

尝试db.AttachTo()而不是db.Attach()

如上所述here

“在ObjectContext上调用AttachTo以将对象附加到对象上下文中设置的特定实体。如果对象具有null(在Visual Basic中为Nothing)EntityKey值,也执行此操作。”

编辑:实际上,在这种情况下你可能需要调用ApplyPropertyChanges()。

编辑2:您可以使用以下代码为对象构建实体密钥:

public EntityKey GetEntityKey(string entitySetName, object keyValue)
{
  IEnumerable<KeyValuePair<string, object>> entityKeyValues =
    new[]
    {
      new KeyValuePair<string, object>("Id", keyValue)
    };

  var key = new EntityKey(string.Concat("YOUR_OBJECT_CONTEXT_NAME.", entitySetName), entityKeyValues);
  return key;
}

然后你会根据名为'Id'的单个数据库列为实体键调用此类内容:

var entityKey = GetEntityKey(“Customer”,23);

我在自己的EF代码中使用了类似的方法,除了使用Generic类型参数以避免必须使用字符串作为实体类名。

答案 2 :(得分:1)

这个怎么样

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, Department dept)
{
    Department tmp = new Department()
    {
        Id = dept.Id
    };
    try
    {
        db.Departments.Attach(dept, tmp);
        db.Save();
    }
}

也许tmp-part可以在Attach部分之后交换为对UpdateModel的调用,但我不确定。

编辑:只需查看附件(实体e,实体原件)上的文档,它确实用e替换原件(或相应地更新原件或w / e)。

答案 3 :(得分:0)

我不建议在您的MVC应用程序中使用POCO。 您应该使用DTO或模型。

也许您应该先通过id检索对象,然后将参数提供的值替换为edit方法,然后保存更改。 您收到错误是因为您没有首先取消模型。

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model) {
var entity=from m in db.Models where m.Id == Model.id select m;
Model entityAttached=entity.FirstOrDefault();
//replace all the new values in you object
db.SaveChanges();
}

当您通过id获取它时,

或deattach对象,并在您想要在edit方法中保存新值时将其附加回来。