失去Oracle数据库连接后如何恢复NHibernate

3

我有一个长时间运行的应用程序,使用NHibernate.ISessionFactory连接到Oracle数据库。

偶尔会出现数据库离线的情况(例如周末维护),但即使数据库恢复在线,后续查询仍会失败,并显示以下异常(也显示内部异常):

NHibernate.Exceptions.GenericADOException: could not execute query
[ select .....]

  >> Oracle.ManagedDataAccess.Client.OracleException: ORA-03135: Connection lost contact

    >> OracleInternal.Network.NetworkException: ORA-03135: Connection lost contact

      >> System.Net.Sockets.SocketException: An established connection 
         was aborted by the software in your host machine

重新启动应用程序可以恢复功能,但我希望应用程序能够在不重启的情况下自动适应,并"重置"连接。当遇到此异常时,我已尝试使用我的ISessionFactory尝试以下操作:
sf.EvictQueries();
sf.Close();
sf = null;
sf = <create new session factory>

在重新创建ISessionFactory后仍然看到相同的异常。我认为这是因为NHibernate在某种连接池中缓存了底层损坏的连接?

如何说服NHibernate创建一个真正新的连接(或者甚至只是完全重置所有状态),从而允许我的应用程序自行修复连接问题,而无需重新启动应用程序?

编辑: 根据A_J的答案,请注意我已经为每个数据库请求调用using(var session = _sessionFactory.OpenSession())


连接池是ADO.Net的责任,而不是NHibernate的责任。 - Oskar Berggren
1个回答

1
我怀疑您在启动时打开了ISession(调用ISessionFactory.OpenSession()),并在应用程序结束时关闭它。对于任何长时间运行的应用程序,这都是错误的方法。
您应该在较低级别的时间管理连接。在Web应用程序中,通常会每个请求处理一次。在您的情况下,您应该找到应该是什么。如果您的Windows服务在指定时间后执行某些活动,则Timer_Tick事件是不错的地方。
我无法建议您的应用程序中可能的位置;您需要自己找出来。

编辑1

查看您的编辑和评论,我认为这与NHibernate无关。可能是连接池将断开/陈旧的连接返回给NHibernate。
请参阅thisthis的已接受答案。

我在问题中应该提到,我对每个请求都调用using (var session = _sessionFactory.OpenSession())。因此没有长时间运行的会话(至少我不知道) - 只有长时间运行的SessionFactory。谢谢 - 我会更新问题以澄清。 - jlb83
感谢提供的链接。由于我只在晚上失去数据库连接,所以测试花了几天时间。我注意到我的连接字符串有一个“Min Pool Size”,但没有“Max Pool Size”。从阅读资料中得知,如果我将“Max Pool Size”设置为N,那么也许第二天早上经过N(自动)重试后,我就能回到正常状态。然而,事实证明将“Max Pool Size”设置为10实际上解决了问题——甚至不需要任何重试——查询在第二天早上“就可以工作”。我不理解这一点,所以接下来几天会继续关注它……但看起来它是有效的。 - jlb83

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接