Где обрабатывать StaleObjectStateException - PullRequest
1 голос
/ 24 февраля 2012

Должен ли я переносить вызовы в хранилище с блоком try-catch (с целью перехвата / обработки StaleObjectStateException) внутри соответствующего контроллера в приложении ASP.NET MVC или это должно происходить внутри реализации хранилища?

Также, как мне обработать исключение, сообщите пользователю.Насколько я понимаю, откат не планируется?

Спасибо!

Ответы [ 2 ]

3 голосов
/ 24 февраля 2012

Проблемы сводятся к другому вопросу: где и как обрабатывать одновременную модификацию сущностей?То есть: пользователь A и пользователь B редактируют одну и ту же запись, и когда тот, кто сохраняет запись позже (пользователь B), получает исключение StaleObjectStateException, поскольку версия, отредактированная им, устарела.

Вот несколько идей:

  1. Принудительно сделать версию пользователя B "правильной", используя грубую силу, например, путем извлечения текущей версии записи изБД и применить к нему все состояние версии пользователя B.Это проблематично, если пользователь A изменил, например, поле «E-Mail address», а пользователь B изменил поле «User name».При таком подходе все, что сделал пользователь A, исчезло.При таком подходе вы ловите StaleObjectStateException и исправляете все внутри хранилища.

  2. «Умный» подход: аналогично подходу 1 все фиксируется внутри хранилища (т. Е. Он ловит и обрабатываетStaleObjectStateException полностью), но он использует знание предметной области, чтобы выборочно применять только некоторые из изменений, внесенных пользователем B.Например, если пользователь A изменил адрес электронной почты, а пользователь B изменил имя пользователя, эти изменения не исключают друг друга, поэтому хранилище может обновлять только адрес электронной почты.Это хорошо работает, если два аспекта записи были изменены одновременно, которые напрямую не зависят друг от друга.Реализация этого решения может быть довольно сложной, в зависимости от того, насколько «умным» вы хотите быть.

  3. Отклонить одновременные изменения внутри хранилища.В этом случае, если возникает исключение StaleObjectStateException, репозиторий должен сообщить, что не смог сохранить запись.Это может на самом деле просто позволить исключению всплыть, но тогда вы пропускаете NHibernate, например, к контроллеру.Вместо этого вы можете просто добавить свое собственное исключение с более полезными деталями, которые имеют значение для вашего домена.В этой ситуации контроллер является хорошим местом для обнаружения этого исключения.Затем у вас есть различные варианты действий, например:

    • Сообщите пользователю, что запись не может быть сохранена из-за одновременных изменений другим пользователем, и отбросьте все изменения, заставив его сделать всес нуля.Это, конечно, болезненно для пользователя и должно выполняться только в том случае, если это действительно происходит редко.
    • Информировать пользователя о проблеме и позволить ему решить, что делать, например, форсировать свои изменения или начать заново.

Хотя это выходит за рамки вашего вопроса, я надеюсь, что это все равно поможет вам.

2 голосов
/ 24 февраля 2012

Если вы правильно используете DI , размещение такого рода управления исключениями в контроллере нарушит ваше разделение задач.

Контроллеры принадлежат к уровню представления, а уровень представления -не знает, что вы используете для хранения данных, а StaleObjectStateException - это материал NHibernate.

...