1

try-catch我应该在 ASP.NET MVC 应用程序中的相应控制器内使用块(旨在 catch/handle )包装对存储库的调用,StaleObjectStateException还是应该在存储库实现中进行?

另外我该如何处理异常,通知用户。据我了解,没有回滚的意图?

谢谢!

4

2 回答 2

3

这些问题归结为一个不同的问题:在哪里以及如何处理实体的并发修改?即:用户 A 和用户 B 编辑同一条记录,而稍后保存该记录的用户(用户 B)由于他编辑的版本现在已过期而收到 StaleObjectStateException。

这里有一些想法:

  1. 通过蛮力强制使用户 B 的版本成为“正确”版本,例如通过从数据库中检索记录的当前版本并将用户 B 版本的整个状态应用于它。如果用户 A 已更改例如“电子邮件地址”字段而用户 B 已更改“用户名”字段,则这是有问题的。使用这种方法,用户 A 所做的一切都消失了。在这种方法中,您将捕获 StaleObjectStateException 并修复存储库中的所有内容。

  2. “智能”方法:与方法 1 类似,所有内容都固定在存储库中(即,它完全捕获并处理 StaleObjectStateException),但它使用领域知识选择性地仅应用用户 B 所做的一些更改。例如,如果用户 A 更改了电子邮件地址,而用户 B 更改了用户名,则这些更改不会相互排斥,因此存储库只能更新电子邮件地址。如果记录的两个方面已同时更改且不直接相互依赖,则此方法效果很好。根据您想要的“智能”程度,实施此解决方案可能相当复杂。

  3. 拒绝存储库内的并发更改。在这种情况下,如果 StaleObjectStateException 发生,存储库需要报告它无法保存记录。它实际上可能只是让异常冒泡,但随后您将 NHibernate 泄漏到例如控制器。相反,您可以使用对您的域有意义的更有用的详细信息抛出您自己的异常。在这种情况下,控制器是捕获该异常的好地方。然后,您有不同的选择,例如:

    • 通知用户由于另一个用户同时更改而无法保存记录,并丢弃所有更改,迫使他从头开始做所有事情。这对用户来说当然是痛苦的,只有在这种情况很少发生时才应该这样做。
    • 将问题告知用户并让他决定做什么,例如强制更改或重新开始。

虽然这超出了您的问题,但我希望这仍然对您有所帮助。

于 2012-02-24T18:41:04.773 回答
2

如果您正确使用DI,将这种异常管理放在控制器中会破坏您的关注点分离。

控制器属于表示层,表示层不知道您使用什么来存储数据,而 StaleObjectStateException 是 NHibernate 的东西。

于 2012-02-24T14:40:35.053 回答