问题
I am using nhibernate and the nhibernate profile what keeps throwing this alert.
Use of implicit transactions is discouraged"
I actually wrap everything in a transaction through ninject
public class NhibernateModule : NinjectModule
{
public override void Load()
{
Bind<ISessionFactory>().ToProvider<NhibernateSessionFactoryProvider>().InSingletonScope();
Bind<ISession>().ToMethod(context => context.Kernel.Get<ISessionFactory>().OpenSession()).InRequestScope()
.OnActivation(StartTransaction)
.OnDeactivation(CommitTransaction);
}
public void CommitTransaction(ISession session)
{
if (session.Transaction.IsActive)
{
session.Transaction.Commit();
}
}
public void StartTransaction(ISession session)
{
if (!session.Transaction.IsActive)
{
session.BeginTransaction();
}
}
}
So this should wrap everything in a transaction and it seems to work with anything that is not lazy loading.
If it is lazy loading though I get the error. What am I doing wrong.
回答1:
This is, in fact, still an implicit transaction, or relatively close to it. The injector is blissfully ignorant of everything that's happened between activation and deactivation and will happily try to commit all your changes even if the state is incorrect or corrupted.
What I see is that you're essentially trying to cheat and just have Ninject automatically start a transaction at the beginning of every request, and commit the transaction at the end of every request, hoping that it will stop NH from complaining. This is extremely bad design for several reasons:
- You are forcing a transaction even if the session is not used at all (i.e. opening spurious connections).
- There is no exception handling - if an operation fails or is rolled back, the cleanup code simply ignores that and tries to commit anyway.
- This will wreak havoc if you ever try to use a
TransactionScope
, because the scope will be completed before the NH transaction is. - You lose all control over when the transactions actually happen, and give up your ability to (for example) have multiple transactions within a single request.
The NH Profiler is exactly right. This isn't appropriate use of NH transactions. In fact, if you're lazy loading, the transaction might end up being committed while you're still iterating the results - not a good situation to be in.
If you want a useful abstraction over the transactional logic and don't want to have to twiddle with ISession
objects then use the Unit Of Work pattern - that's what it's designed for.
Otherwise, please code your transactions correctly, with a using
clause around the operations that actually represent transactions. Yes, it's extra work, but you can't cheat your way out of it so easily.
来源:https://stackoverflow.com/questions/6245708/how-to-wrap-lazy-loading-in-a-transaction