c# - 执行 SaveChanges 时排除未修改的字段

标签 c# sql-server asp.net-mvc entity-framework entity-framework-6

当我想保存从表单发回的对象,但从生成的 SQL 语句中排除特定字段时,会出现问题。在这种情况下,我不想在用户编辑表单中包含密码字段。

编辑 HttpPost Controller 方法包含以下内容:

db.Users.Attach(user);
db.Entry(user).State = EntityState.Modified;
db.Entry(user).Property(x => x.Password).IsModified = false;
db.SaveChanges();

我假设 .IsModified 语句意味着生成的 SQL 将包含一个没有密码字段的 UPDATE 语句,因此不会用数据库中的 null 覆盖现有密码值。

然而,事实并非如此,EF 的工作方式似乎略有不同。我的用户类及其关联的元数据类没有指定密码字段是必需的,但是在执行时,调用 SaveChanges 时会抛出“需要密码字段”DbEntityValidationException。

一种解决方案是将密码字段及其值作为隐藏表单字段包含在内,这在大多数情况下就足够了,但在这种情况下不是一个好主意,因为密码、散列或其他方式是相当敏感的数据。

在进一步检查时,似乎在我们使用数据库优先方法的这种情况下,.edmx 文件在密码字段上包含“not null”指令。当 EF 开始执行实际保存时,将对此进行检查并引发异常。

在我看来这并不完全直观,但一旦知道它就可以变通。

我的解决方案是为排除的字段提供一个值并保留 .IsModified 语句。这意味着 DbEntityValidationException 不会被抛出,因为 EF 看到密码字段包含一个值(如 .edmx 文件中所规定的),但由于 IsModified 为假,因此不会实际写入数据库。例如

user.Password = "not required";
db.Users.Attach(user);
db.Entry(user).State = EntityState.Modified;
db.Entry(user).Property(x => x.Password).IsModified = false;
db.SaveChanges();

是否有更好的解决方案,因为使用上面的虚拟值似乎有点 hack?

最佳答案

您还没有真正解释为什么您不想保存密码字段,我假设它只是因为您不知道该值是什么,并且在您当前的代码中它被设置为 NULL。

您可以使用 ViewModel 与您的网页绑定(bind),并且只提供所需的字段(因此在您的情况下,不是密码字段)。当用户 POST 返回数据时,您可以从数据库加载用户,仅设置您需要的字段,然后将数据保存回来。密码字段将保持不变。

例如,假设用户表是这样的:

ID
UserName
Password
FullName

你会有一个 View 模型类

public class UserViewModel
{
    public int ID { get; set; }
    public string UserName { get; set; }
    public string FullName { get; set; }
}

当数据从客户端回发到服务器时:

using (MyEntity db = new MyEntity())
{
    User u = db.Users.Find(userViewModel.ID);
    u.UserName = userViewModel.UserName;
    u.FullName = userViewModel.FullName;
    db.SaveChanges();
}

关于c# - 执行 SaveChanges 时排除未修改的字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35458980/

相关文章:

c# - 嵌套事务范围,必需 -> 抑制 -> 必需

asp.net-mvc - ASP.NET MVC 与 Azure B2C 刷新 ID token 问题

asp.net - 为什么一个简单的 ASP.NET MVC 网站需要完全信任

c# - 更改 WPF 数据网格中自动生成的列类型

JavaScript $.each 函数

sql-server - SQL server 2005中 "select 123.866"的数据类型是什么?

c# - 使用 Web API, Entity Framework 如何知道对象中发生了什么变化?

jquery - 动态对象和AJAX调用mvc

c# - WPF 中的任务锁定 UI

c# - 如何初始化 Task<List<string>> 参数?