NHibernate.Exceptions.GenericADOException来自代码但不是来自DB的超时

时间:2013-08-22 11:15:32

标签: sql-server nhibernate timeout

我有一个NHibernate查询(填充EXTJS网格)

它向数据库发出2个查询,一个用于获取记录计数(用于分页目的),另一个用于获取前N行以填充网格。

从代码中,我一直在Select count(*)语句中获得异常。

NHibernate.Exceptions.GenericADOException: 
Failed to execute multi criteria[SQL: 
 SELECT count(*) as y0_ FROM RecordView this_ inner join ProcessesView 
 process1_ on this_.ProcessId=process1_.Id inner join BusinessModelsView 
 businessmo3_ on process1_.BusinessModelId=businessmo3_.Id inner join BatchesView
 batch2_ on this_.BatchId=batch2_.Id WHERE this_.ProcessId = ?;
] ---> System.Data.SqlClient.SqlException: Timeout expired.  
The timeout period elapsed prior to completion of the operation or the server 
is not responding.

但是,如果我将该确切查询放入SSMS窗口并运行它,它将在<1秒内执行。

NHibernate在这里做了什么“有趣”的事情。是否存在执行计划/缓存问题。我完全不知道为什么会这样。

2 个答案:

答案 0 :(得分:2)

每当我遇到此错误时,原因是锁定从不性能)。有两个会议开幕(意外)。两人都开始了交易,其中一人锁定了桌子。

问题可能是某些未被处理的会话,或“非预期的”单身......持有已打开的会话。

这个答案并不像我希望的那样直截了当,但我确信方向。因为我经历了相同的(并且有罪)

BTW:正如Oskar Berggren向你发现的那样,30秒的超时与<property name="command_timeout">30</property>有关。我相信,如果你愿意提供60,120 ......因为锁定它是不够的

答案 1 :(得分:1)

SQL SERVER

不会以相同的方式处理您的两个查询
  • 您的NH查询是在第一次执行时编译的,基于表统计信息和参数的第一个值。生成的查询计划将用于所有后续调用,无需考虑参数值

  • 你的SQL查询(我想,你用实际值替换?)根据统计数据和值对每个值进行不同的编译。

您的第一个NH编辑可能产生了一个查询计划,对第一个值有效,但在一般情况下则不然。

首先,我建议:

  • 你指望一个投影(比如在主表id上),因为它比count(*)稍微有效一点,允许DB在可能的情况下只对索引起作用
  • 您检查是否错过了查询所需的任何索引
  • 您检查所有表统计信息是否为最新

如果这不能改善执行时间,这篇文章提供了一些选项(重新编译可能是好的): Query executed from Nhibernate is slow, but from ADO.NET is fast