views:

306

answers:

3

I am writing a simple ASP.NET MVC using session per request and transaction per request patterns (custom HttpModule). It seems to work properly, but.. the performance is terrible (a simple page loads ~7 seconds). For every http request, graphical resources incuding (all images on the site) a transaction is created and that seems to delay the loading times (without the transactions loading times per one image are ~1-10 ms with transactions they are over 1 second). What is the proper way to manage transactions in ASP.NET MVC + NH stack?

When i've put all transactions into my repository methods, for some obscure reasons I got 'implicit transactions' warning in NHProf (the SQL statements were executed outside transaction, even that in code session.Save()/Update()/etc methods were invoked within transaction 'using' scope and before transaction.Commit() call) BTW are implicit transactions really bad?

+1  A: 

The implicit transactions occurs when you do not place your statements in a transaction. The implicit is that if you don't explicitly declare a transaction each one of your statements runs in its own transaction. So yeah it's bad. That bad? I don't know enough about what you're working on to judge.

I do the same thing that you're doing with session per request but I do not get anywhere near the same performance numbers. I would recommend looking into turning on log4net for NHibernate and see what it's doing. Your application should only be creating the session factory and proxy factories one time (managing the session factory would be one of the few places I would use a singleton). That's really the only thing I can think of that might cause it.

Min
Thanks for the hint, SessionFactory is however created only once in application lifetime.
adrin
+1  A: 

There are a couple issues here:

First, regarding your performance issues. Are you making sure that the ISessionFactory is only instantiated once? It's a very expensive object to create, so it should probably be a singleton in your web app that's created on Application_Start, rather than in Application_BeginRequest. My guess as to why you're getting such poor performance is that you're creating a new ISessionFactory per request rather than once for the entire application.

Second, regarding implicit transactions, they're not that bad, but from the way you're describing your code you shouldn't be getting these errors. Are you sure you're executing your calls within a transaction? It's possible that you're accessing some lazy-load properties from the .aspx and .ascx pages that may execute outside of your transaction.

Kevin Pang
ISessionFactory is instantiated only once, it seems that invoking session.BeginTransaction() takes up to 1-2 seconds sometimes :/ so thats what causes bad performance.I am using postgresql server running on linux.. hmm maybe i shall test with another db or try an approach that uses ActionFilters for transaction management
adrin
A: 

You need to use a contextual session so that a new session and transaction are not created on every request for an image resource, etc. See my answer to this question. This change should improve performance significantly. This is probably also the root cause of the implicit transaction warnings.

Another frequent performance issue with NH applications is using log4net with a DEBUG level.

Edit: Min and Kevin Pang's answers are also good advice so I won't bother repeating their statements.

Jamie Ide
contextual sessions are very likely to solve my problem, but I still dont know when should I start the transaction?
adrin
You can start and end the transaction in your HttpModule, that's a reasonable approach in my opinion. I would implement contextual sessions first and see if you still have a performance problem before looking elsewhere. I prefer to manage the transaction on the page so that I can respond to exceptions "better".
Jamie Ide