NHibernate command_timeout不适用于批处理

时间:2013-05-08 16:25:47

标签: nhibernate timeout batch-processing

今天我遇到了超时问题。

我有以下用于创建SessionFactory的配置:

 <property name="adonet.batch_size">50</property>
 <property name="command_timeout">600</property>

我不将它存储在web.config中,而是存储在手动传递给配置的XML文件中:

configuration.Configure(cfgFile)

因此,我可以拥有多个具有独立配置的会话工厂(每个数据库)。

command_timeout似乎仅在NHibernate不使用批次时才有效。如果SQL命令是批处理的,那么对于一些大批量我得到:

NHibernate.Exceptions.GenericADOException: could not execute batch command.
[SQL: SQL not available] --->
System.Data.SqlClient.SqlException: Timeout expired. 
The timeout period elapsed prior to completion of the operation or the server is not responding.

在搜索解决方案时,我发现了一篇文章解释了为什么会这样: http://ronaldrosiernet.azurewebsites.net/Blog/2013/04/20/timeout_in_nhibernate_batched_sessions

问题的原因是,对于SQL批处理,NHibernate使用的是Cfg.Environment.CommandTimeout而不是command_timeout,它在创建会话时传递给配置。

我找到了一种在创建配置时实施变通方法的方法:

if (configuration.Properties.ContainsKey(NHibernate.Cfg.Environment.CommandTimeout))
    NHibernate.Cfg.Environment.Properties[NHibernate.Cfg.Environment.CommandTimeout] = 
            configuration.Properties[NHibernate.Cfg.Environment.CommandTimeout];

现在我的同事们说暂停现在似乎已经解决了。

但令我困惑的是以下主题: https://forum.hibernate.org/viewtopic.php?f=25&t=983105

说:

  

属性NHibernate.Cfg.Environment.Properties返回一个副本   全局属性,所以你不能修改它。

如果NHibernate.Cfg.Environment.Properties是一个只读副本,那么为什么我的解决方法似乎工作正常?它是稳定的还是这个修复程序不可靠并且在其他一些情况下可能会中断?

我还在NHibernate JIRA中发现了一个相关的问题: https://nhibernate.jira.com/browse/NH-2153

如果他们说他们在v3.1.0中修复了command_timeout的问题,那为什么我仍然需要在NHibernate v3.3.2中使用我的解决方法。 ?

有人对此有任何见解吗?

1 个答案:

答案 0 :(得分:6)

使用批次时遇到同样的问题。 Nhibernate类SqlClientBatchingBatcher使用来自Environment.GlobalProperties的命令超时,它是只读的。我发现只有两种方法可以在SqlClientBatchingBatcher.currentBatch命令

上设置超时

1)在app.config文件中使用超时

<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>
    <property name="command_timeout">120</property>
  </session-factory>
</hibernate-configuration>

2)设置环境。

FieldInfo field = typeof(global::NHibernate.Cfg.Environment).GetField("GlobalProperties", System.Reflection.BindingFlags.NonPublic |                                     System.Reflection.BindingFlags.Static);
Dictionary<string, string> gloablProperties = field.GetValue(null) as Dictionary<string, string>;
gloablProperties.Add("command_timeout","120");