У меня есть шаблон доступа к хранилищу данных:
IRepository<T>
{
.. query members ..
void Add(T item);
void Remove(T item);
void SaveChanges();
}
Представьте себе сценарий, в котором у меня есть хранилище пользователей, пользователи имеют уникальное имя пользователя, если я создаю нового пользователя с существующим именем пользователя (представьте, что у меня есть тупой слой пользовательского интерфейса, который не проверяется), когда Я добавляю его в репозиторий, все в порядке ... когда я нажимаю SaveChanges, мой репозиторий пытается сохранить элемент в базе данных, моя база данных, к счастью, применяет эти правила и выдает мне отмененное исключение из-за нарушения уникального ключа.
Мне кажется, что обычно эта проверка выполняется на уровне НАД хранилищем, слои, которые его вызывают, знают, что должны обеспечить это правило, и будут предварительно проверять и выполнять (надеюсь, в какой-то области видимости транзакции, чтобы избежать рас, но не всегда кажется возможным с существующим средним невежеством).
Разве мой репозиторий не должен применять эти правила? что произойдет, если мой носитель будет тупым, например, плоская база данных без каких-либо проверок целостности?
И если хранилище проверяет подобные вещи, как они будут информировать вызывающих абонентов о нарушении таким образом, чтобы вызывающий мог точно определить, что пошло не так, исключения кажутся плохим способом справиться с этим, потому что они относительно дороги и трудно специализироваться вплоть до конкретного нарушения ..
Я играл с шаблоном Can, например. CanAdd с Add, add вызовет CanAdd и выдаст недопустимое исключение операции, если can возвращает нарушение. CanAdd также возвращает список нарушений о том, что пошло не так ... таким образом я могу начать укладывать эти подпрограммы через стек ... например, вышеприведенный сервисный уровень также будет иметь метод "Can", который будет возвращать отчет о репозиториях + любые дополнительные нарушения, которые он хотел проверить (такие как более сложные бизнес-правила, например, какие пользователи могут вызывать определенные действия).
Проверка данных является такой фундаментальной, но я чувствую, что нет реального руководства для того, как надежно обрабатывать более сложные требования проверки.
Отредактируйте, дополнительно в этом случае, как вы обрабатываете проверку сущностей, которые находятся в репозитории и обновляются через отслеживание изменений .. например:
using (var repo = ...)
{
var user = repo.GetUser('user_b');
user.Username = 'user_a';
repo.SaveChanges(); // boom!
}
Как вы можете себе представить, это вызовет исключение ... углубляясь в кроличью нору, представьте, что у меня есть система проверки, когда я добавляю пользователя, и я делаю что-то вроде этого:
using (var repo = ...)
{
var newUser = new User('user_c');
repo.Add(newUser); // so far so good.
var otherUser = repo.GetUser('user_b');
otherUser.Username = 'user_c';
repo.SaveChanges(); // boom!
}
В этом случае проверка при добавлении пользователя была бессмысленной, так как «нисходящие» действия могли бы нас все равно испортить, правилу добавления проверки нужно было бы проверить фактическое постоянное хранилище И все элементы, поставленные в очередь для сохранения.
Это все еще не останавливает предыдущую проблему с отслеживанием изменений ... так что теперь я должен начать проверять вызов сохранения изменений? похоже, что было бы огромное количество нарушений, которые могли бы произойти из-за явно не связанных действий.
Возможно, я прошу нереальную, совершенную сеть безопасности?
Заранее спасибо,
Стивен.