2016-11-09 72 views
3

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

偶尔数据库脱机时(如周末的维护),但即使一旦数据库恢复联机,后续查询失败,以下异常(内部异常所示):

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())

+0

连接池是ADO.Net的职责,而不是NHibernate。 –

回答

1

我怀疑您在启动时打开ISession(致电ISessionFactory.OpenSession()),并在应用程序结束时关闭它。这对任何长时间运行的应用程序来说都是错误的。

您应该在较低的时间级别管理连接。在Web应用程序中,这通常按每个请求处理。就你而言,你应该找到应该做的。如果你的Windows服务在指定的时间之后做了一些活动,那么Timer_Tick事件就是好地方。

我无法建议您的应用程序中可能存在的位置;你需要自己找出答案。

编辑1

看你的编辑和评论,我不认为这有什么与NHibernate。可能是连接池正在返回到NHibernate的断开/过时连接。

请参阅thisthis接受的答案。

+0

我应该在问题中提到,我为每个请求调用'(使用(var session = _sessionFactory.OpenSession())'。因此,没有长时间运行的会话(我知道) - 只有长时间运行的SessionFactory。谢谢 - 我会更新这个问题来澄清。 – jlb83

+0

感谢您的链接。花了几天测试,因为我只在一夜之间失去了数据库连接。我注意到我的连接字符串有一个“最小池大小”,但没有“最大池大小”。从阅读的角度来看,我想也许如果我将“最大池大小”设置为N,那么可能在第二天早上N(自动)重试,我会回到工作状态。但是,似乎将“Max Pool Size”设置为10实际上已经解决了这个问题 - 甚至不需要任何重试 - 第二天早上的查询“正常工作”。我不明白这一点,所以在接下来的几天里会密切关注它......但它似乎有效。 – jlb83

相关问题