Как обернуть ленивую загрузку в транзакцию?

Я использую 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 от жалоб. Это очень плохой дизайн по нескольким причинам:

  1. Вы форсируете транзакцию, даже если сеанс вообще не используется (например, открытие поддельных соединений).
  2. Обработка исключений отсутствует - если операция завершается неудачно или откатывается, код очистки просто игнорирует это и в любом случае пытается зафиксировать.
  3. Это приведет к хаосу, если вы когда-нибудь попытаетесь использовать TransactionScope, потому что область будет завершена до того, как транзакция NH будет.
  4. Вы теряете контроль над фактическим выполнением транзакций и теряете способность (например) выполнять несколько транзакций в одном запросе.

NH Profiler совершенно прав. Это неуместное использование транзакций NH. На самом деле, если вы лениво загружаете, транзакция может завершиться фиксацией, пока вы еще итерируете результаты - не очень хорошая ситуация.

Если вы хотите получить полезную абстракцию над транзакционной логикой и не хотите использовать ISession Затем объекты используют шаблон Unit Of Work - для этого он и предназначен.

В противном случае, пожалуйста, кодируйте свои транзакции правильно, с using пункт вокруг операций, которые фактически представляют транзакции. Да, это дополнительная работа, но вы не можете обмануть свой выход из нее так легко.

Другие вопросы по тегам