执行SaveChanges

时间:2016-02-17 14:09:44

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

如果我想保存从表单发回的对象,但从结果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。

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

在进一步检查时,似乎在我们使用数据库第一种方法的情况下,.edmx文件在Password字段中包含'not null'指令。当EF执行实际保存时,会检查并引发异常。

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

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

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

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

2 个答案:

答案 0 :(得分:1)

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

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

例如,假设User表是这样的:

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

答案 1 :(得分:0)

使用存储过程方法,您不必担心实体框架,从实体框架调用存储过程并在sql语句中更新您的表而不更新密码字段