这是一个非常好的问题。默认情况下,我发现只要启用了更改跟踪(这是默认情况下除非关闭),Entity Framework将会很好地向数据库应用您要求更改的内容。
因此,如果您只改变对象的1个字段,然后调用SaveChanges(),EF只会在调用SaveChanges()时更新该字段。
这里的问题是,当您将视图模型映射到实体对象时,所有的值都会被覆盖。这里是我的处理是这样的:
在这个例子中,有一个名为的人一个单一的实体:
Person
======
Id - int
FirstName - varchar
Surname - varchar
Dob - smalldatetime
现在让我们说,我们要创建一个将只更新杜伯视图模型,并留下所有其他领域究竟如何,这是我如何做到这一点。
首先,创建一个视图模型:
public class PersonDobVm
{
public int Id { get; set; }
public DateTime Dob { get; set; }
public void MapToModel(Person p)
{
p.Dob = Dob;
}
}
现在写的代码大致如下(你必须改变它来匹配您的上下文的名称等):
DataContext db = new DataContext();
Person p = db.People.FirstOrDefault();
// you would have this posted in, but we are creating it here just for illustration
var vm = new PersonDobVm
{
Id = p.Id, // the Id you want to update
Dob = new DateTime(2015, 1, 1) // the new DOB for that row
};
vm.MapToModel(p);
db.SaveChanges();
的MapToModel方法可能会更复杂,并在将视图模型字段分配给实体对象之前执行各种附加检查。
无论如何,当调用SaveChanges结果是下面的SQL:
exec sp_executesql N'UPDATE [dbo].[Person]
SET [Dob] = @0
WHERE ([Id] = @1)
',N'@0 datetime2(7),@1 int',@0='2015-01-01 00:00:00',@1=1
所以,你可以清楚地看到,实体框架并没有试图更新任何其他领域 - 只是杜伯领域。
我知道你的例子中你想避免用手来编码每个任务,但我认为这是最好的方法。你把它全部放在你的虚拟机中,这样它就不会抛弃你的主代码,这样你就可以满足特定的需求(即那里的复合类型,数据验证等)。另一种选择是使用AutoMapper,但我不认为它们是安全的。如果您在虚拟机中使用AutoMapper并将“Dob”拼写为“Doob”,则它不会将“Doob”映射到“Dob”,也不会告诉您!它会默默地失败,用户会认为一切正常,但变化不会被保存。如果你在虚拟机中拼写“Dob”为“Doob”,编译器会提醒你MapToModel()引用了“Dob”,但你的虚拟机中只有一个名为“Doob”的属性。
我希望这可以帮助你。
创建视图模型..只添加你想要的领域..设定值 – JamieD77
即使我创建视图模型;更新到我的表“Person”时仍存在同样的问题。如果我缺少一些东西,请纠正我的问题 –
您的viewmodel是否只显示了您显示的25个字段? – JamieD77