В некоторой единице/интеграционных тестах кода мы хотим проверить, что корректное использование второго кэша уровня используется нашим кодом.
На основе кода, представленного 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
}
Но это всегда возвращается 0 для количества Запроса. Никакие sql операторы не регистрируются.
Однако, если я использую Профилировщика Nhibernate и вызываю это в моем тестовом сценарии:
NHibernateProfiler.Intialize()
Где NHProf использует аналогичный подход для получения вывода входа от NHibernate для анализа через log4net и т.д. затем, мой QueryCounter начинает работать.
Похоже, что я пропускаю что-то в своем коде для получения log4net, настроенного правильно для входа nhibernate sql... у кого-либо есть какие-либо указатели на том, что еще я должен сделать для получения sql вход вывода от Nhibernate?
Дополнительная информация:
Logging.config:
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};
}
}
Который работает просто великолепно, после того как статистика включена.
Есть другой (более простой, 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;
Ну, вот и все. Надеюсь, это поможет вам, как помогло мне.
С уважением,
Филипе