try-catch
我应该在 ASP.NET MVC 应用程序中的相应控制器内使用块(旨在 catch/handle )包装对存储库的调用,StaleObjectStateException
还是应该在存储库实现中进行?
另外我该如何处理异常,通知用户。据我了解,没有回滚的意图?
谢谢!
try-catch
我应该在 ASP.NET MVC 应用程序中的相应控制器内使用块(旨在 catch/handle )包装对存储库的调用,StaleObjectStateException
还是应该在存储库实现中进行?
另外我该如何处理异常,通知用户。据我了解,没有回滚的意图?
谢谢!
这些问题归结为一个不同的问题:在哪里以及如何处理实体的并发修改?即:用户 A 和用户 B 编辑同一条记录,而稍后保存该记录的用户(用户 B)由于他编辑的版本现在已过期而收到 StaleObjectStateException。
这里有一些想法:
通过蛮力强制使用户 B 的版本成为“正确”版本,例如通过从数据库中检索记录的当前版本并将用户 B 版本的整个状态应用于它。如果用户 A 已更改例如“电子邮件地址”字段而用户 B 已更改“用户名”字段,则这是有问题的。使用这种方法,用户 A 所做的一切都消失了。在这种方法中,您将捕获 StaleObjectStateException 并修复存储库中的所有内容。
“智能”方法:与方法 1 类似,所有内容都固定在存储库中(即,它完全捕获并处理 StaleObjectStateException),但它使用领域知识选择性地仅应用用户 B 所做的一些更改。例如,如果用户 A 更改了电子邮件地址,而用户 B 更改了用户名,则这些更改不会相互排斥,因此存储库只能更新电子邮件地址。如果记录的两个方面已同时更改且不直接相互依赖,则此方法效果很好。根据您想要的“智能”程度,实施此解决方案可能相当复杂。
拒绝存储库内的并发更改。在这种情况下,如果 StaleObjectStateException 发生,存储库需要报告它无法保存记录。它实际上可能只是让异常冒泡,但随后您将 NHibernate 泄漏到例如控制器。相反,您可以使用对您的域有意义的更有用的详细信息抛出您自己的异常。在这种情况下,控制器是捕获该异常的好地方。然后,您有不同的选择,例如:
虽然这超出了您的问题,但我希望这仍然对您有所帮助。
如果您正确使用DI,将这种异常管理放在控制器中会破坏您的关注点分离。
控制器属于表示层,表示层不知道您使用什么来存储数据,而 StaleObjectStateException 是 NHibernate 的东西。