Как обернуть ленивую загрузку в транзакцию?
Я использую nhibernate и профиль nhibernate, который продолжает выдавать это предупреждение.
Использование неявных транзакций не рекомендуется "
Я на самом деле обернуть все в транзакции через 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();
}
}
}
Так что это должно обернуть все в транзакции, и, похоже, работает с чем-то, что не ленивая загрузка.
Если загрузка ленивая, я получаю сообщение об ошибке. Что я делаю неправильно.
1 ответ
Фактически это все еще неявная транзакция или относительно близкая к ней. Инжектор блаженно не знает обо всем, что произошло между активацией и деактивацией, и с радостью попытается зафиксировать все ваши изменения, даже если состояние неверно или повреждено.
Я вижу, что вы, по сути, пытаетесь обмануть, и просто Ninject автоматически запускает транзакцию в начале каждого запроса и фиксирует транзакцию в конце каждого запроса, надеясь, что это остановит NH от жалоб. Это очень плохой дизайн по нескольким причинам:
- Вы форсируете транзакцию, даже если сеанс вообще не используется (например, открытие поддельных соединений).
- Обработка исключений отсутствует - если операция завершается неудачно или откатывается, код очистки просто игнорирует это и в любом случае пытается зафиксировать.
- Это приведет к хаосу, если вы когда-нибудь попытаетесь использовать
TransactionScope
, потому что область будет завершена до того, как транзакция NH будет. - Вы теряете контроль над фактическим выполнением транзакций и теряете способность (например) выполнять несколько транзакций в одном запросе.
NH Profiler совершенно прав. Это неуместное использование транзакций NH. На самом деле, если вы лениво загружаете, транзакция может завершиться фиксацией, пока вы еще итерируете результаты - не очень хорошая ситуация.
Если вы хотите получить полезную абстракцию над транзакционной логикой и не хотите использовать ISession
Затем объекты используют шаблон Unit Of Work - для этого он и предназначен.
В противном случае, пожалуйста, кодируйте свои транзакции правильно, с using
пункт вокруг операций, которые фактически представляют транзакции. Да, это дополнительная работа, но вы не можете обмануть свой выход из нее так легко.