处理StaleObjectStateException的位置

时间:2012-02-24 13:36:15

标签: c# asp.net-mvc nhibernate exception-handling optimistic-locking

我应该在ASP.NET MVC应用程序中的相应控制器内用try-catch块(旨在捕获/处理StaleObjectStateException)来调用存储库,还是应该在存储库实现中进行? / p>

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

谢谢!

2 个答案:

答案 0 :(得分:3)

问题归结为一个不同的问题:在何处以及如何处理实体的并发修改?即:用户A和用户B编辑相同的记录,并且稍后保存记录的用户(用户B)获得StaleObjectStateException,因为他编辑的版本现在已过期。

以下是一些想法:

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

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

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

    • 告知用户由于其他用户的并发更改而无法保存记录并将所有更改丢弃,迫使他从头开始执行所有操作。这对用户来说当然是痛苦的,只有在很少发生这种情况时才应该这样做。
    • 告知用户该问题并让他决定做什么,例如迫使他改变或重新开始。
  4. 虽然这超出了你的问题,但我希望这对你有帮助。

答案 1 :(得分:2)

如果您正确使用DI将这种异常管理置于控制器中会破坏您的关注点。

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