如何防止EF验证在DBContext.SaveChanges()期间未映射的属性

时间:2011-08-13 15:52:08

标签: c# asp.net-mvc-3 entity-framework-4.1

我的用户模型有两个[NotMapped]字符串属性Password和ConfirmPassword。这些是未映射的,因为我将密码保存为字节数组(在salting之后),因此在用户模型中有两个额外的属性(映射)InternalPassword和Salt。

问题是当我使用用户模型更改密码时,实体框架会抛出DBEntityValidation错误,指出“需要密码属性”。我在这里理解的是,EF正在尝试在保存之前验证我的模型,并且由于未设置Password / ConfirmPassword,因此抛出此错误。这提出了以下问题:

1)如果属性密码被明确表示为[NotMapped],为什么EF在保存期间验证它? 2)如果EF在保存期间执行验证,并且在绑定期间也执行相同的操作(控制器操作方法中的I.E.),它是否不会影响性能? (验证两次) 3)解决此错误的推荐方法是什么? (如果我将Password属性显式设置为虚拟值,则错误消失。)

编辑:我删除了代码,因为它很长,可能是没有答案的原因。如果有人想看看,我可以在下面添加。

2 个答案:

答案 0 :(得分:10)

EF中的自动验证是某种奇怪的功能 - 我不喜欢它。您可以阅读this article以查找有关如何验证所选属性的一些信息,但我希望您必须手动触发该验证并通过调用来关闭全局验证:

context.Configuration.ValidateOnSaveEnabled = false;

NonMappedAttribute的问题很有意思。我没有深入研究EFv4.1中的验证实现,但如果实现是围绕与基于数据注释的通用验证相同的规则构建的,那么它仅使用从ValidationAttribute派生的属性 - NotMappedAttribute是不是来自ValidationAttribute

这是此类实现的另一个问题 - 它结合了映射定义和验证,但这两个功能并不相同,不应由同一API实现。

@alun删除了他的答案 - 你问题的有效答案。您的验证属于视图模型,具体取决于用户正在执行的操作。它不属于持久性模型。为什么?正是由于您当前的问题 - 持久性模型只能包含单个验证集,并且应用程序中的每个操作都必须确保满足该集合的验证条件=您必须确保PasswordConfirmPassword均已填充如果你当前的操作没有要求它=>问题

答案 1 :(得分:0)

旧线程,但是由于我遇到了与EF6完全相同的问题,请允许我分享我的经验,以防其他人搜索相同的东西。

问题:完全相同:“密码”和“确认密码” 2用户类的[未映射]字段。尝试保存新记录时,我得到了验证例外,因为这两个字段都是必需的。

调查:我注意到在更新用户记录时,我没有任何问题。搜索有什么区别,我发现我已经覆盖了Validate方法

public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext)

用于验证MVC模型,并且EF6正在显示我的自定义错误消息! 瞧! EF6也使用了这种Validate方法! (并且由于我的代码中的错误,它触发了错误)。

结论:保存实体时,EF6将触发Validate方法,任何“ ValidationResult”都将阻止保存记录。