我想知道在 ASP.NET MVC 应用程序中验证数据库约束(例如 UNIQUE)的最佳方法是什么,在构建时考虑到 DDD,其中底层是应用程序层(应用程序服务)、域层(域模型)和基础设施层(持久性逻辑、日志记录等)。
我一直在查看很多 DDD 示例,但其中许多没有提到如何在存储库中进行验证(我想这就是这种验证适合的地方)。如果您知道这样做的任何示例,请分享它们,我们将不胜感激。
更具体地说,我有两个问题。您将如何执行实际验证?您会通过查询数据库明确检查客户名称是否已经存在,还是尝试将其直接插入数据库并捕获错误(如果有)(看起来很乱)?我更喜欢第一个,如果选择这个,应该在存储库中完成,还是应该是应用程序服务的工作?
当检测到错误时,如何将其传递给 ASP.NET MVC,以便用户可以很好地了解错误?最好使用,ModelStateDictionary
以便在表单上轻松突出显示错误。
在 Microsoft Spain 的 N-Lyered 应用程序中,他们使用IValidatableObject
接口并将最简单的属性验证放在实体本身上,例如:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var validationResults = new List<ValidationResult>();
if (String.IsNullOrWhiteSpace(this.FirstName))
validationResults.Add(new ValidationResult(Messages.validation_CustomerFirstNameCannotBeNull, new string[] { "FirstName" }));
return validationResults;
}
在实体被持久化之前,会调用 Validate 消息来确保属性有效:
void SaveCustomer(Customer customer)
{
var validator = EntityValidatorFactory.CreateValidator();
if (validator.IsValid(customer)) //if customer is valid
{
_customerRepository.Add(customer);
_customerRepository.UnitOfWork.Commit();
}
else
throw new ApplicationValidationErrorsException(validator.GetInvalidMessages<Customer>(customer));
}
然后可以在 MVC 应用程序中捕获 ApplicationValidationErrorsException,并且可以解析验证错误消息并将其插入到ModelStateDictionary
.
我可以将所有验证逻辑添加到 SaveCustomer 方法中,例如使用给定列(唯一列)查询数据库检查客户是否已经存在。也许这没关系,但我宁愿validator.IsValid
(或类似的东西)为我做这件事,或者在基础设施层再次执行验证(如果它属于这里,我不确定)。
你怎么看?你怎么做呢?我对深入了解分层应用程序中的不同验证技术非常感兴趣。
可能的解决方案#1
如果验证逻辑无法在表示层中完成(如 Iulian Margarintescu 建议的那样)并且需要在服务层中完成,您将如何将验证错误传递给表示层?
Microsoft 在这里有一个建议(参见清单 5)。您如何看待这种方法?