如果我想保存从表单发回的对象,但从结果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();
是否有更好的解决方案,因为使用上面的虚拟值似乎有点像黑客?
答案 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语句中更新您的表而不更新密码字段