Вот сценарий:
- Веб-приложение ASP.NET MVC2
- Entity Framework 4 (чистый POCO, пользовательский контекст данных)
- Шаблон репозитория
- Единица работы
- Внедрение зависимостей
- Контроллер-посредник сервисного уровня -> Репозиторий
В общем, все классные вещи. :)
Поток событий для базовой операции пользовательского интерфейса («Добавление сообщения»):
- вызовы контроллера метод Add (Post) на уровне обслуживания
- Вызовы сервисного уровня Добавить (T) в хранилище
- Вызовы репозитория AddObject (T) в пользовательском контексте данных
- вызовы контроллера Commit () на единицу работы
Теперь я пытаюсь понять, где я могу поставить свое подтверждение.
На этом этапе мне нужно два типа проверки:
- Простая, независимая проверка POCO, такая как «сообщение должно иметь заголовок». Это выглядит естественным для аннотаций данных на POCO.
- Сложная проверка бизнеса, например "невозможно добавить комментарий к заблокированной записи". Это не может быть сделано аннотациями данных.
Теперь я читаю «Программирование Entity Framework, второе издание» Джули Лерман (что очень хорошо понимается) и пытаюсь подключиться к событию SavingChanges , чтобы выполнить «last- минутная проверка Это был бы хороший способ убедиться, что проверка всегда происходит всякий раз, когда я делаю «что-то» (добавляю, изменяю, удаляю), но это также немного запаздывает IMO (поскольку элементы уже находятся в менеджере состояний) - так что я могу сделать, если проверка не удалась, удалить их?
Конечно, я мог бы заставить мой POCO реализовать интерфейс (скажем, "IValidatable") и вызывать метод для этого интерфейса во время этого события.
Но это кажется "слишком поздно" для проверки бизнеса - это консенсус?
Здесь я в основном ищу руководство, я пытаюсь разработать интеллектуальную схему многократного использования для сложной бизнес-логики, учитывая мою вышеупомянутую архитектуру.
Еще один изогнутый шар для вас - как вы знаете, POCO с EF означают, что POCO имеют все свойства в БД - поэтому у меня может быть свойство "PostID" с аксессорами get / set ( как EF нужно получить / установить эти свойства).
Но проблема в том, что "PostID" - это столбец удостоверения , так как я могу защитить поле от установки расширенного набора? Например, если я (по какой-то причине) сделаю следующее:
var post = service.FindSingle(10);
post.PostId = 10;
unitOfWork.Commit();
Это вызовет исключение SqlException. Как я могу предотвратить это? Я не могу «спрятать» свойство (сделать его частным или даже внутренним), так как POCO находятся в отдельной сборке с репозиторием.
Замечание о проверке - я планирую создать пользовательские исключения (исходя из исключения). Поэтому, когда проверка не проходит, мне нужно выбросить эти исключения.
Таким образом, я могу кодировать что-то вроде этого на моем контроллере:
[HttpPost]
public ActionResult AddPost(Post post)
{
try
{
IUnitOfWork uow = new UnitOfWork();
postService.Add(post);
uow.Commit();
}
catch(InvalidPostOperation ipo)
{
// add error to viewmodel
}
}
Придется ли мне вручную проверять уровень обслуживания каждый раз, когда я делаю Add? Тогда как я могу справиться с Save? (поскольку это относится к единице работы, а не к служебному слою).
Итак, чтобы этот вопрос не был «повсеместным», вот мои вопросы:
- Простая проверка POCO - должно ли это быть сделано с аннотациями данных? Плюсы / минусы / подводные камни?
- При каких обстоятельствах (если таковые имеются) мы должны подключаться к событию SavingChanges контекста данных EF, чтобы обеспечить проверку?
- Где мне проводить комплексную проверку бизнеса? В сервисе explicity или в методе POCO (который я могу вызвать из сервиса). Как я могу создать интеллектуальную / многоразовую схему?
- Как мы можем "скрыть" автоматически сгенерированные свойства POCO от вмешательства?
Любые мысли были бы наиболее ценными.
Приносим свои извинения, если этот пост "слишком длинный", но это важная проблема, и она может быть решена разными способами, поэтому я хотел предоставить всю информацию, чтобы получить наилучший ответ.
Спасибо.
EDIT
Следующий ответ полезен, но я все еще (в идеале) ищу больше мыслей. Кто-нибудь еще?