I am having a problem where a criteria query in NHibernate is executes in less then a second when I run it in a unit test, but when I try to run it from the context of my web application, it takes over a minute. Both are hitting the same database for the same data.
My NHibernate mapping:
var properties = new Dictionary<string, string>();
var configuration = new Configuration();
properties.Add("connection.provider", "NHibernate.Connection.DriverConnectionProvider");
properties.Add("proxyfactory.factory_class", "NHibernate.Bytecode.DefaultProxyFactoryFactory, NHibernate");
properties.Add("connection.release_mode", "on_close");
properties.Add("current_session_context_class", "web");
properties.Add("dialect", "NHibernate.Dialect.MsSql2005Dialect");
properties.Add("connection.connection_string_name", "DBConnection");
configuration.Properties = properties;
SessionFactory = configuration.BuildSessionFactory();
The only difference in this mapping between tests and the web app is the current_session_context_class, where it is thread_static in tests, but that does not seem to be the problem.
The criteria for the query:
var reports = Session.CreateCriteria<Report>()
.SetFetchMode("Site", FetchMode.Join)
.SetFetchMode("Actions", FetchMode.Join)
.SetResultTransformer(new DistinctRootEntityResultTransformer())
.Add(Subqueries.PropertyIn("Site",
SiteCriteria.GetSitesForUserWithPermission(user, Permission.SomePermission))))
.List<Report>();
I have tried using NH Profiler to help, but it did not offer any useful suggestions.
edit: Looking further in nhprofiler, I see that in the test for example, the query duration is 1ms / 313ms (Database only / Total).
But for the website it just took me 1ms / 43698ms. It seems that NHibernate is having a hard time mapping the actual objects.
The difference between the unit tests and the web app is that unit tests aren’t logged.
I added to our log4net.config:
And the problem went away.
It was outputting a lot of stuff like this: