8

コードの一部のユニット/統合テストでは、コードで 2 番目のレベルのキャッシュが正しく使用されていることを確認したいと考えています。

ここでAyendeによって提示されたコードに基づいています:

http://ayende.com/Blog/archive/2006/09/07/MeasuringNHibernatesQueriesPerPage.aspx

まさにそれを行うための簡単なクラスを作成しました。

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
}

ただし、Query count には常に 0 が返されます。SQL ステートメントはログに記録されていません。

ただし、Nhibernate Profiler を使用して、テスト ケースでこれを呼び出すと、次のようになります。

NHibernateProfiler.Intialize()

NHProf が同様のアプローチを使用して、log4net などを介した分析のために NHibernate からのログ出力をキャプチャすると、QueryCounter が機能し始めます。

nhibernate sql をログに記録するために log4net を正しく構成するために、コードに何かが欠けているようです... 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>

show_sql: 真

jfneis の応答に基づいて、NHibernate のファクトリ統計のみを使用する、はるかに単純なクラスを作成しました。

public class QueryCounter
{
  long _startCount;

  QueryCounter()
  {
  }

  public int QueryCount
  {
    get { return (int) (UnitOfWork.CurrentSession.SessionFactory.Statistics.QueryExecutionCount - _startCount); }
  }

  public static QueryCounter Start()
  {
    return new QueryCounter {_startCount = UnitOfWork.CurrentSession.SessionFactory.Statistics.QueryExecutionCount};
  }
}

統計が有効になると、これはうまく機能します。

4

1 に答える 1

13

キャッシュがヒットしているかどうか、またはクエリが実行されているかどうかをアサートする別の(より単純なIMO)方法があります。それは、統計を使用することです。

まず、NH構成ファイルで統計を有効にする必要があります。

 <property name="generate_statistics">true</property>

その後、状況がどうなっているのかを知りたいときはいつでも、セッションファクトリに問い合わせることができます。あなたはL2キャッシュテストについて話しました、それであなたはそのような何かを持つことができました:

        // 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;

まあ、それだけです。これが私を助けてくれたようにあなたを助けてくれることを願っています。

よろしく、

フィリペ

于 2010-04-23T18:01:53.197 に答える