2010-04-22 44 views
8

Trong một số kiểm tra đơn vị/tích hợp của mã, chúng tôi muốn kiểm tra việc sử dụng đúng bộ nhớ cache cấp thứ hai đang được sử dụng bởi mã của chúng tôi.Đếm số truy vấn được thực hiện bởi NHibernate trong một bài kiểm tra đơn vị

Dựa trên mã được trình bày bởi Ayende ở đây:

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

Tôi đã viết một lớp đơn giản để thực hiện điều đó:

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

Với việc sử dụng dự định:

using (var counter = QueryCounter.Start()) 
{ 
    // ... do something 
    Assert.Equal(1, counter.QueryCount); // check the query count matches our expectations 
} 

Nhưng nó luôn trả về 0 cho số truy vấn. Không có câu lệnh sql nào đang được ghi lại.

Tuy nhiên nếu tôi tận dụng Nhibernate Profiler và gọi này trong trường hợp thử nghiệm của tôi:

NHibernateProfiler.Intialize() 

đâu NHProf sử dụng một phương pháp tương tự để nắm bắt sản lượng khai thác gỗ từ NHibernate để phân tích qua log4net vv sau đó QueryCounter của tôi bắt đầu làm việc .

Có vẻ như tôi đang thiếu thứ gì đó trong mã của mình để cấu hình log4net đúng cách để đăng nhập nhibernate sql ... có ai có bất kỳ gợi ý nào về những thứ khác mà tôi cần làm để lấy đầu ra đăng nhập sql từ Nhibernate không?

Thông tin thêm:

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: true

Dựa trên phản ứng jfneis, tôi đã viết một lớp đơn giản hơn nhiều mà chỉ sử dụng thống kê nhà máy 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}; 
    } 
} 

Chỉ hoạt động tốt khi đã bật thống kê.

+0

Bittercoder, tôi ra khỏi máy dev của tôi ngay bây giờ vì vậy tôi không thể gửi mã, nhưng có bạn cố gắng sử dụng thống kê để làm điều đó? Tôi cũng đã phải đối mặt với loại vấn đề này để kiểm tra L2 và Thống kê, nơi đủ để kịch bản của tôi. Quay lại văn phòng (12h kể từ bây giờ) Tôi sẽ đăng (nếu vẫn cần) một câu trả lời hoàn chỉnh. Hy vọng điều này sẽ giúp cho đến khi có. – jfneis

+0

Trong cấu hình nhibernate của bạn, bạn có đặt show_sql là true? Xin vui lòng bạn cũng có thể đăng log4net.config của bạn? – mhanney

+0

Có, đã thử nó với show_sql được đặt thành true và false. Mặc dù tôi nghĩ rằng show_sql đã không sử dụng log4net và chỉ cần bán các câu lệnh sql để stdout? Tôi đã bao gồm cấu hình log4net của mình trong câu hỏi đầu tiên. Thực tế là NHibernateProfiler.Initialize() sau đó khiến lớp học của tôi làm việc cho tôi thấy rằng có lẽ một số cấu hình log4net có lập trình mà tôi đang thiếu. – Bittercoder

Trả lời

13

Có cách khác (đơn giản hơn, IMO) để xác nhận xem bộ nhớ cache có bị truy cập hay không hoặc nếu truy vấn đang được thực hiện: sử dụng Thống kê.

Trước hết, bạn phải kích hoạt liệu thống kê trong tập tin cấu hình NH của bạn:

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

Sau đó, bạn có thể yêu cầu nhà máy phiên của bạn bất cứ khi nào bạn muốn như thế nào mọi thứ đang đi. Bạn đã nói chuyện về việc thử nghiệm bộ nhớ cache L2, vì vậy bạn có thể có một cái gì đó như thế:

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

Nhưng, nếu những gì bạn thực sự muốn là số lượng truy vấn, có rất nhiều lựa chọn khác trong giao diện thống kê:

 sessionFactory.Statistics.QueryExecutionCount; 
     sessionFactory.Statistics.TransactionCount; 

Vâng, đúng vậy. Hy vọng điều này sẽ giúp bạn như đã giúp tôi.

Kính trọng,

Filipe

+0

Tôi đã thống kê một cái nhìn, và không tìm thấy bất kỳ số liệu thống kê truy vấn - nhưng tôi đã nhìn vào ISessionStatistics, ISessionFactory.Statistics (IStatistics). Sẽ cung cấp cho nó một đi :) – Bittercoder

+0

Thực hiện lớp đơn giản bằng cách sử dụng số liệu thống kê - công trình tuyệt vời - cảm ơn sự giúp đỡ José! – Bittercoder

+0

Tôi rất vui khi biết rằng nó đã giúp bạn. – jfneis

Các vấn đề liên quan