Мне интересно, как лучше всего выполнить проверку ограничений базы данных (например, UNIQUE) в приложении ASP.NET MVC, построенном с учетом DDD, где базовыми уровнями являются уровень приложения (службы приложений), уровень домена (модель домена) и уровень инфраструктуры (логика постоянства, ведение журнала и т. д.).
Я просмотрел множество примеров DDD, но во многих из них не упоминается, как выполнять проверку в репозитории (я полагаю, что именно здесь подходит этот тип проверки). Если вы знаете какие-либо образцы, делающие это, пожалуйста, поделитесь ими, мы будем очень признательны.
Точнее, у меня два вопроса. Как бы вы выполнили фактическую проверку? Вы бы явно проверили, существует ли имя клиента, запросив базу данных, или вы попытаетесь вставить его непосредственно в базу данных и отловить ошибку, если она есть (кажется беспорядочной) ? Я предпочитаю первый вариант, и если выбрать его, следует ли это делать в репозитории или это должна быть работа службы приложений?
Когда ошибка обнаружена, как бы вы передали ее в ASP.NET MVC, чтобы пользователь мог хорошо проинформироваться об ошибке? Предпочтительно использовать ModelStateDictionary
, чтобы ошибка была легко выделена в форме.
В приложении N-Lyered от Microsoft Spain используется интерфейс 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));
}
Затем ApplicationValidationErrorsException может быть перехвачено в приложении MVC, а сообщения об ошибках проверки могут быть проанализированы и вставлены в файл ModelStateDictionary
.
Я мог бы добавить всю логику проверки в метод SaveCustomer, например. запрос к базе данных, проверяющий, существует ли уже клиент, используя данный столбец (УНИКАЛЬНЫЙ). Может быть, это нормально, но я бы предпочел, чтобы validator.IsValid
(или что-то подобное) делало это за меня, или чтобы проверка выполнялась еще раз на уровне инфраструктуры (если она относится сюда, я не уверен).
Как вы думаете? Как ты делаешь это? Мне очень интересно получить больше информации о различных методах проверки в многоуровневых приложениях.
Возможное решение №1
В случае, когда логика проверки не может быть реализована на уровне представления (как предлагает Юлиан Маргаринтеску) и должна выполняться на уровне обслуживания, как бы вы передавали ошибки проверки на уровень представления?
У Microsoft есть предложение здесь (см. листинг 5). Что вы думаете о таком подходе?