计算NHibernate在单元测试中执行的查询数

计算NHibernate在单元测试中执行的查询数,nhibernate,caching,count,log4net,nhprof,Nhibernate,Caching,Count,Log4net,Nhprof,在一些代码的单元/集成测试中,我们希望检查代码是否正确使用了二级缓存 根据Ayende提供的代码: 为此,我编写了一个简单的类: public class QueryCounter : IDisposable { CountToContextItemsAppender _appender; public int QueryCount { get { return _appender.Count; } } public void Dispo

在一些代码的单元/集成测试中,我们希望检查代码是否正确使用了二级缓存

根据Ayende提供的代码:

为此,我编写了一个简单的类:

public class QueryCounter : IDisposable
{
    CountToContextItemsAppender _appender;

    public int QueryCount
    {
      get { return _appender.Count; }
    }

    public void Dispose()
    {
      var logger = (Logger) LogManager.GetLogger("NHibernate.SQL").Logger;
      logger.RemoveAppender(_appender);
    }

    public static QueryCounter Start()
    {
      var logger = (Logger) LogManager.GetLogger("NHibernate.SQL").Logger;

      lock (logger)
      {
        foreach (IAppender existingAppender in logger.Appenders)
        {
          if (existingAppender is CountToContextItemsAppender)
          {
            var countAppender = (CountToContextItemsAppender) existingAppender;

            countAppender.Reset();

            return new QueryCounter {_appender = (CountToContextItemsAppender) existingAppender};
          }
        }

        var newAppender = new CountToContextItemsAppender();
        logger.AddAppender(newAppender);
        logger.Level = Level.Debug;
        logger.Additivity = false;

        return new QueryCounter {_appender = newAppender};
      }
    }

    public class CountToContextItemsAppender : IAppender
    {
      int _count;

      public int Count
      {
        get { return _count; }
      }

      public void Close()
      {
      }

      public void DoAppend(LoggingEvent loggingEvent)
      {
        if (string.Empty.Equals(loggingEvent.MessageObject)) return;
        _count++;
      }

      public string Name { get; set; }

      public void Reset()
      {
        _count = 0;
      }
    }
}
预期用途:

using (var counter = QueryCounter.Start())
{
  // ... do something 
  Assert.Equal(1, counter.QueryCount); // check the query count matches our expectations
}
但对于查询计数,它总是返回0。没有记录任何sql语句

但是,如果我使用Nhibernate Profiler并在测试用例中调用它:

NHibernateProfiler.Intialize()
当NHProf使用类似的方法从NHibernate捕获日志输出,以便通过log4net等进行分析时,我的QueryCounter开始工作

看起来我的代码中缺少了一些东西,无法正确配置log4net以记录nhibernate sql。。。有没有人对我还需要做什么才能从Nhibernate获得sql日志输出有任何指示

其他信息:

Logging.config:

<log4net>

  <appender name="trace" type="log4net.Appender.TraceAppender, log4net">
    <layout type="log4net.Layout.PatternLayout,log4net">
      <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] &amp;lt;%P{user}&amp;gt; - %m%n" />
    </layout>
  </appender>

  <appender name="console" type="log4net.Appender.ConsoleAppender, log4net">
    <layout type="log4net.Layout.PatternLayout,log4net">
      <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] &amp;lt;%P{user}&amp;gt; - %m%n" />
    </layout>
  </appender>

  <appender name="debug" type="log4net.Appender.DebugAppender, log4net">
    <layout type="log4net.Layout.PatternLayout,log4net">
      <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] &amp;lt;%P{user}&amp;gt; - %m%n" />
    </layout>
  </appender>

  <logger name="NHibernate.SQL" additivity="false">
    <level value="DEBUG" />
    <appender-ref ref="ConsoleAppender" />
  </logger>

  <root>
    <priority value="DEBUG" />
    <appender-ref ref="trace" />
    <appender-ref ref="console" />
    <appender-ref ref="debug" />
  </root>

</log4net>
一旦启用了统计信息,它就可以正常工作。

还有另一种(更简单,IMO)方法可以断言是否正在命中缓存或是否正在执行查询:使用统计信息

首先,您必须在NH配置文件中启用统计信息:

 <property name="generate_statistics">true</property>
但是,如果您真正想要的是查询计数,那么统计界面中还有很多其他选项:

        sessionFactory.Statistics.QueryExecutionCount;
        sessionFactory.Statistics.TransactionCount;
好了,就这样。希望这能像帮助我一样帮助你

问候,


Filipe

我查看了统计数据,没有找到任何查询统计数据-但我正在查看ISessionStatistics、ISessionFactory.statistics(IStatistics)。将试一试:)使用统计实现的简单类-效果很好-感谢José的帮助!我很高兴知道它对您有所帮助。QueryExecutionCount没有实际显示执行的SELECT语句的数量?我有一个N+1的情况,我正在努力改进,单次会话列表调用创建了第一个select,然后又创建了27个select。但是QueryExecutionCount仍然是1。我认为PrepareStatementCount是您想要的。在您的nhibernate配置中,您是否已将show\u sql设置为true?请您也发布您的log4net.config?是的,在show_sql设置为true和false的情况下进行了尝试。虽然我认为show_sql没有使用log4net,只是将sql语句转储到stdout?现在,我已经在最初的问题中包括了我的log4net配置。NHibernateProfiler.Initialize()然后导致我的类工作的事实向我表明,这可能是我缺少的一些编程log4net配置。BiterCoder,我现在已经离开了我的开发机器,所以我无法发布代码,但您是否尝试使用统计信息来实现这一点?在测试L2和统计数据时,我也遇到了这样的问题,因为这些数据足以支持我的场景。回到办公室(12小时后),我会发布一个完整的答案(如果仍然需要的话)。希望这有帮助,直到有。您正在调用log4net.Config.XmlConfigurator.Configure();你的应用程序何时启动?应该是。如果真是这样的话我会很惊讶的,我只是想提一下。
        // act
        MappedEntity retrievedEntity = session.FindById(entity.Id);
        long preCacheCount = sessionFactory.Statistics.SecondLevelCacheHitCount;
        retrievedEntity = session.FindById(entity.Id);
        long postCacheCount = sessionFactory.Statistics.SecondLevelCacheHitCount;
        // assert
        Assert.AreEqual(preCacheCount + 1, postCacheCount);
        sessionFactory.Statistics.QueryExecutionCount;
        sessionFactory.Statistics.TransactionCount;