MVC3与EF 4.1和EntityState.Modified

时间:2011-12-05 23:45:09

标签: asp.net-mvc-3 entity-framework-4

使用MVC3更新对象

我有一个可以修改的模型,请参阅下面的示例:

[HttpPost]
public ActionResult Edit(Company c)
{
       if (ModelState.IsValid)
       {
           db.Entry(c).State = EntityState.Modified;
           db.SaveChanges();
           return RedirectToAction("Index");
       }
       return View(c);
}

模型的其他字段未在视图中显示且用户无法修改,但当我单击提交按钮时,未在视图中显示的字段设置为null。

我可以以某种方式让EF知道不修改某些字段吗?感谢。

3 个答案:

答案 0 :(得分:12)

通常最好不要直接绑定到实体对象,而是创建一个编辑模型并绑定到该模型。

毕竟......什么方法可以阻止有人回复你不希望用这种方法改变的价值?

这里的主要问题是mvc模型绑定在上下文中更改了模型中的属性,因此实体框架不知道哪些值已更改(因此哪些值应更新)

您已使用db.Entry(c).State = EntityState.Modified;略微缓解了这一点,但这告诉实体框架整个记录已更新。

我通常会做以下事情:

  1. 首先绑定到专门针对此控制器的模型
  2. 创建要更新的实体类的实例,相应地设置ID并将其附加到上下文
  3. 将实体上的属性更新为与绑定到的模型相同(对象已附加,因此实体框架正在跟踪现在正在更改的列)
  4. 的SaveChanges
  5. 第3步有点单调乏味,因此请考虑使用像automapper这样的工具来简化工作

    编辑:

        [HttpPost]
        public ActionResult Edit(Company c)
        {
            if (ModelState.IsValid)
            {
                Company dbCompayObjct = new Company { companyId = c.companyId };
                db.Company.Attach(dbCompayObjct);
    
                dbCompanyObjct.CompanyName = c.CompanyName;
                dbCompanyObjct.City = c.City;
    
                db.SaveChanges();
    
                return RedirectToAction("Index");
            } 
            return View(c);
        }
    

答案 1 :(得分:3)

您显然用不完整的记录覆盖现有记录。当您使用上述方法时,它将完全替换现有方法。

您需要填写您不想用现有值替换的所有字段,或者您需要获取现有记录并修改要修改的字段,然后保存它。

答案 2 :(得分:0)

反思并不总是邪恶的,有时它是你的朋友:

public ActionResult Edit(Company c)
{
   if (ModelState.IsValid)
   {
        Company UpdateC = db.Company.find(c.CompanyID);        
        foreach (var property in typeof(Company).GetProperties())
        {
            var propval = property.GetValue(c);
            if (propval != null)
            {
                property.SetValue(UpdateC, propval);
            }
        }

        db.SaveChanges();  
        return RedirectToAction("Index");
   }
   return View(c);
}