NHibernate: Criteria query slow in web app but fast in unit tests, why?

旧街凉风 提交于 2019-12-24 09:59:22

问题


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.


回答1:


The difference between the unit tests and the web app is that unit tests aren't logged. I added to our log4net.config:

<filter type="log4net.Filter.LevelRangeFilter">
    <levelMin value="WARN" />
</filter>

And the problem went away.

It was outputting a lot of stuff like this:

2011-07-21 13:07:17,479 DEBUG [14] LoadContexts - attempting to locate loading collection entry [CollectionKey[Actions#d6adfe87-a7d4-4821-bb10-4ef76fcf614d]] in any result-set context
2011-07-21 13:07:17,481 DEBUG [14] LoadContexts - collection [CollectionKey[Actions#d6adfe87-a7d4-4821-bb10-4ef76fcf614d]] not located in load context



回答2:


Visual Studio Debugger is the culprit! Try running your app with debugging off (ctrl+F5) or run it from outside of visual studio. I did this and my app ran as fast as the unit test.

If this solves the problem there are a few things you can do to speed up VS Debugger like removing all the breakpoints and deleting the .suo file. For more info see this post: Slow debugging issue in Visual Studio

Other things that might help:

  1. Try setting the correct default database for the user you're connected as. Do this on sql server itself (using SSMS for example) not in any of the configs.
  2. Turn log4net logging completely off using the threshold property like so in the app/web config: <log4net debug="false" threshold="off">.
  3. Set the default_schema in your hibernate config.
  4. Turn show_sql off in the hibernate config.


来源:https://stackoverflow.com/questions/6777561/nhibernate-criteria-query-slow-in-web-app-but-fast-in-unit-tests-why

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!