使用绑定在控制器中编辑模型会删除绑定中未包含的属性

时间:2015-10-05 17:22:42

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

Controller上的以下代码用于编辑具有属性MyClass的模型name, attr1, attr2, attr3, ... , attr10。绑定[Bind(Include = "ID,name,attr1,attr2")]不包含大多数属性,结果是在将更改保存到数据库后将其清除。

我想要的是要更新的绑定属性,但保留其余属性的旧值,而无需在绑定上指定它们(因为有很多并且它们经常更改)。这是完整的编辑功能代码:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "ID,name,attr1,attr2")] MyClass item)
{
    if (ModelState.IsValid)
    {
        db.Entry(item).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(item);
}

我该如何实现这种行为?

2 个答案:

答案 0 :(得分:3)

虽然Erik的回答在技术上是正确的,但我认为这有点反模式。

首先,当你编辑一个实体时,你不应该只是将发布的对象直接传递给数据库来覆盖那里的任何东西。

您的编辑操作应将id(或其他一些标识值)作为参数:

public ActionResult Edit(int id, Foo model)

然后,你应该从数据库中提取对象并检查被修改的东西是否正确并且仍然存在:

var foo = db.Foos.Find(id);
if (foo == null)
{
    return new HttpNotFoundResult();
}

最后,将应该修改的值从发布的数据映射到数据库中的实体:

foo.name = model.name;
// etc.

现在,当您保存时,只会修改您要修改的值,并且无需明确篡改更改跟踪。

答案 1 :(得分:2)

首先,了解失去这些价值的原因非常重要。我们来看看EntityState.Modified

  

修改了对象上的一个标量属性,并且尚未调用SaveChanges方法。在没有更改跟踪代理的POCO实体中,在调用DetectChanges方法时,已修改属性的状态将更改为“修改”。保存更改后,对象状态将更改为“未更改”。

由于未从数据库中检索对象(它不在上下文中),因此修改了所有属性,从而将对象保存到数据库,保存所有属性。

您只需要将特定属性标记为已更改,而不是标记整个对象已更改:

db.Users.Attach(item);
db.Entry(item).Property(x => x.ID).IsModified = true;
db.Entry(item).Property(x => x.name).IsModified = true;
db.Entry(item).Property(x => x.att1).IsModified = true;
db.Entry(item).Property(x => x.att2).IsModified = true;
db.SaveChanges();

(如果您的ID是密钥,请不要将其标记为已修改)