在执行“保存更改”时排除未修改的字段

本文关键字:保存更改 未修改 字段 排除 执行 | 更新日期: 2023-09-27 18:34:56

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

编辑 HttpPost 控制器方法包含以下内容:

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文件在密码字段上包含一个"非空"指令。当 EF 执行实际保存时,将检查此情况并引发异常。

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

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

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();

有没有更好的解决方案,因为使用上面的虚拟值似乎有点黑客?

在执行“保存更改”时排除未修改的字段

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

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

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

ID
UserName
Password
FullName

您将有一个视图模型类

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();
}

使用存储过程方法,无需担心实体框架,从实体框架调用存储过程并在不更新密码字段的情况下更新 SQL 语句中的表