您可以创建仅包含该表单中可编辑字段的视图模型。
然后在保存更改时,您需要从数据库中检索实体,将视图模型中的字段映射到检索到的实体,最后调用 SaveChanges。
因此,给定实体FooEntity
,您可以创建一个EditFooViewModel
仅包含要编辑的属性的视图模型:
public class FooEntity
{
public int Id {get; set;}
public string Field1 {get; set;}
public string Field2 {get; set;}
public string NonEditableField1 {get; set;}
public string NonEditableField2 {get; set;}
}
public class EditFooViewModel
{
public int Id {get; set;}
public string Field1 {get; set;}
public string Field2 {get; set;}
}
然后在提交表单时,检索实体并使用视图模型值更新它,然后再保存更改。保持示例简单,遵循此想法的控制器方法可能如下所示:
public ActionResult SaveChanges(EditFooViewModel viewModel)
{
... check model state for errors...
//Get the current entity value
var entity = dbContext.FooEntities.Single(e => e.Id == viewModel.Id);
//Map values from view model to entity
entity.Field1 = viewModel.Field1;
entity.Field2 = viewModel.Field2;
//Save changes
dbContext.SaveChanges();
...
}
编辑 - 我什么时候应该使用视图模型?
视图模型将帮助您将控制器/视图与业务层分离。这意味着视图模型可以为您的业务对象提供不同的视图(在单个视图模型中组合多个实体,减少暴露的属性或注意格式化数据!)并且它们将减少对业务层的更改所产生的影响在控制器/视图上,反之亦然。(从简单的更改(例如重命名后端的属性)到更大的更改,例如将业务层公开为 REST json 服务)
它们还将阻止您将任何不需要的属性公开为隐藏字段,或手动将可编辑属性设置为已修改(这与遵循视图模型模式的映射代码非常相似!)。如果您有任何将实体返回为 json 的操作,您还可以避免暴露整个业务对象。另一个好处是,当您忘记在 EF(或您可能正在使用的其他后端)中手动附加和设置修改的属性时,您可以防止细微的错误
确实,它们增加了自己的一些复杂性,主要是一组额外的类(视图模型)以及对视图模型-模型映射代码的需求。(尽管这里有一些工具可以提供帮助,比如 Automapper)
还要考虑到对于许多应用程序,将控制器/视图与后端分离是一项要求。在这些情况下,视图模型是可行的方法。
我还要说,在我看来,与替代方案相比,使用视图模型时添加的额外代码并不算多:
您可以决定为验证中涉及的任何其他字段使用隐藏字段(因此验证成功),然后将模型附加到 EF 上下文,手动设置可编辑属性为已修改。您不需要视图模型类和映射代码,并且您还可以防止额外的数据库命中以在保存之前检索当前实体值。但是,您需要视图中的隐藏字段,以及将每个可编辑属性设置为在 EF 中修改的代码。不要忘记,如果有任何新的验证,您可能需要在视图中添加一个新的隐藏字段。
另一种选择是根本不使用隐藏字段,并且仅在视图中显示您实体中的可编辑字段。保存时,您需要从 EF 中检索实体,手动映射可编辑字段,最后验证并保存。这与使用视图模型几乎相同,但没有视图模型类。在验证和保存之前,您仍然需要从后端检索实体并映射视图中编辑的属性!虽然这在某些情况下可能就足够了,但在其他情况下,您还需要使用视图模型的好处。
然而,这并不意味着您应该在每个应用程序上盲目地使用视图模型。是您知道您的具体场景和要求,因此您需要考虑每种选择的优缺点,并决定哪一种最有意义!