在查询异常后使用NHibernate会话

时间:2012-10-08 08:39:58

标签: nhibernate azure

我们正在尝试实施重试逻辑,以便从Azure环境中的瞬态错误中恢复。

我们正在使用long-running sessions在应用程序事务结束时跟踪并提交一大堆更改(可能会分布在多个Web请求中)。在此过程中,我们需要从数据库中获取其他数据。我们的主要问题是我们无法轻易从db错误中恢复,因为我们无法“重放”所有用户操作。

到目前为止,我们使用了简单的恢复算法:

  • 尝试在长时间运行的会话中执行操作
  • 如果出现错误,请关闭会话,打开新会话并将实体合并到其中
  • 重试操作

就时间而言,这是非常昂贵的方法(对于大型实体层次结构,合并非常长)。所以我们想稍微优化一下。

我们希望在单独的会话中执行查询操作(以保持长时间运行不受影响且安全),并且在成功时,将结果合并回长时间运行的会话。重试在这里相对简单 - 我们只需要打开新会话并再次运行查询。但是,使用这种方法,我们在初始化延迟属性/集合时遇到问题:

  • 如果我们在单独的会话中执行此操作,我们需要将结果合并(许多实体),但合并可能会失败并打破长时间运行的会话
  • 我们尝试了不同的方式将原始实体“移动”到不同的会话,加载详细信息并将其返回,但没有成功(逐出,复制等)

已知statement在异常情况下应丢弃会话。但是,该示例显示了 write 操作。是否仍然适用于读取的那些?我的意思是,如果我保证没有数据写回数据库,我可以重用相同的会话来再次运行查询吗?

对于长时间运行的会话,您对重试逻辑有任何其他建议吗?

1 个答案:

答案 0 :(得分:1)

IMO无法解决您的问题。这将需要花费大量时间来提交所有内容,否则您将需要做大量工作才能将其分解为更小的会话并处理合并时可能发生的每个错误。

要回答有关在异常后使用会话的问题:您不能再信任此会话中的任何内容,甚至不能信任加载的实体。

在Ayende的article中阅读本段内容,了解如果会话中出现异常,请使用recoveryplan构建一个简单的待办事项:

  

然后是错误处理的问题。如果你得到例外   (例如StaleObjectStateException,因为并发冲突),   你的会话及其加载的实体是吐司,因为   NHibernate,会话抛出的异常将会话移动到   未定义的状态。您无法再使用该会话或任何已加载的会话   实体。如果您只有一个全局会话,则意味着您   可能需要重新启动应用程序,这可能不是一件好事   想法。