让我先说这个问题,并说明使用实体框架不适合我们。企业中企业实体验证的首选方法
在我们的财务组织中,我们有跨越解决方案的业务实体。有些人拥有其他人不需要的界面。验证和业务规则必须包含在实体中。
我针对为我生成的DAL和DTO编写代码,这些DAL使用procs在数据库上运行CRUD(可能是SQL可能是Oracle)。
因此,当我创建MVC,WCF,控制台应用程序等。如果可以实现更好的验证方法,问题一直在唠叨。
这里是一个实体对象一个典型的几个特性:
[DefaultValue("")]
public string Branch {
get { return _branch; }
set {
if (value != null && value == _branch) return;
const string propertyName = "Branch";
ValidationInstance.Clear(propertyName);
ValidationInstance.ValidateRequired(propertyName, value);
ValidationInstance.ValidateNumeric(propertyName, value);
ValidationInstance.ValidateLength(propertyName, value, 2);
_branch = value;
if (EntityState != EntityStateType.New)
EntityState = EntityStateType.Changed;
}
}
[DefaultValue(0)]
public decimal HighDefermentMargin {
get { return _highDefermentMargin; }
set {
if (value == _highDefermentMargin) return;
const string propertyName = "HighDefermentMargin";
ValidationInstance.Clear(propertyName);
ValidationInstance.ValidateRange(propertyName, value);
_highDefermentMargin = value;
if (EntityState != EntityStateType.New)
EntityState = EntityStateType.Changed;
}
}
正如你可以看到有进行越来越详细的验证数据注释和显式调用验证类的组合。
在一个MVC应用程序中,我们在ViewModel上苦心地复制了验证,因此我们获得了客户端和服务器端的验证。这里是同一属性的视图模型版本从上面:
[Required]
[Range(0.0, 99.99)]
[Display(Name = "High Deferment Margin")]
public decimal HighDefermentMargin { get; set; }
这里的主要区别是,在实体验证加载错误插入的验证类的错误集合,可以在当时的实体进行查询去拯救自己。如果(!IsValid)则抛出一个包含错误数组的自定义异常。控制器通过它们循环并将它们添加到ModelState中。
我开始研究一些几乎有几百个字段的类。即使它们被面向对象分解,领域的数量仍然非常高。这些都是贷款认证等,对于单个记录有很多数据。必须写出对许多属性的验证使我想吐。我不能只编写一个实用程序来生成实体和验证,因为业务规则是驱动验证的原因,而不是数据库。这意味着一个字段在数据库中可以为空,但不允许根据业务规则保留为空值,或者该字段可以为空,但只有在单独的字段具有值时才是空的等。
所以,可以使用just View Model中的数据注释与实体的实现方式是否相同?我可以为非标准验证编写自定义验证器,然后为更复杂的内容编写业务规则。验证错误是否会从实体中获得更高的级别,以便UI可以像ModelState一样以友好的方式通知用户?其他人在这种情况下做什么?
我有一个建议。在遇到无效输入或在通过业务规则引擎进行验证时规则未满足的任何情况下,只需冒泡该异常,以便可以在Controller中捕获该异常,然后将其添加到modelstate的错误集合中。例如:抛出一个自定义的异常,并且不要在规则引擎中捕获该异常,只需重新抛出,直到它到达控制器。然后使用Html.ValidationSummary()在UI中显示。 – Saravanan 2012-03-16 03:50:01
这样做会奏效 - 但这个想法是为了避免评估集合中的属性或获取并提供更多的AoP设计模式。我已经在房产中找到了收集错误的策略。所有抛出异常都会提供一种不同的方式来向调用者显示错误。这只是交换不同代码的代码。我想消除属性中的代码。 – 2012-03-16 14:09:53
内置的类型默认为必需,您不需要添加该属性。 – RickAndMSFT 2012-03-22 17:07:05