Старые данные возвращаются при обновлении - PullRequest
0 голосов
/ 16 сентября 2018

Я использую TransactionScope с nHibernate . Для работы с вложенными транзакциями я создал вспомогательный класс вместе с TransactionScope . Мой SessionFactory :

 public class SessionFactory
    {
        [ThreadStatic]
        private static ISessionFactory iSessionFactory;
        [ThreadStatic]
        protected static ISession session;
        private static object syncRoot = new Object();

        private static void buildSessionFactory()
        {
            lock (syncRoot)
            {
                if (session == null)
                {
                    if (iSessionFactory == null)
                    {
                        Configuration configuration = new Configuration().Configure("hibernate.cfg.xml");
                        Assembly assembly = Assembly.GetCallingAssembly();
                        iSessionFactory = configuration.BuildSessionFactory();
                    }
                    if (session != null && session.IsOpen)
                        session.Dispose();
                    CurrentSessionContext.Bind(iSessionFactory.OpenSession());
                    session = iSessionFactory.OpenSession();
                }
            }
        }

        public static ISession OpenSession
        {
            get
            {
                if (session == null || !session.IsOpen)
                {
                    session = null;
                    buildSessionFactory();
                }
                return session;
            }
        }
    }

Конфигурация файл с именем hibernate.cfg.xml и имеет вид:

<configuration>
  <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <session-factory>
      <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
      <property name="connection.driver_class">
        NHibernate.Driver.MySqlDataDriver
      </property>
      <property name="dialect">NHibernate.Dialect.MySQL55InnoDBDialect</property>
      <property name="connection.connection_string">connection string here</property>
      <property name="current_session_context_class">thread_static</property>
      <property name="show_sql">true</property>
      <property name="generate_statistics">true</property>
      <mapping assembly="assembly name here"/>
      <!-- Here -->
    </session-factory>
  </hibernate-configuration>
  <system.transactions>
    <machineSettings maxTimeout="00:00:60" />
  </system.transactions>
</configuration>

Вспомогательный класс для управления вложенными транзакциями :

  public class TransactionScopeHelper : SessionFactory, iTransactionScopeHelper
    {
        public static int count = 0;
        public TransactionScope getTransactionScope()
        {
            if (count == 0)
            {
                if (session != null)
                    session.Clear();
            }
            count++;
            return new TransactionScope(TransactionScopeOption.Required);
        }

        public void complete(TransactionScope tx)
        {
            count--;
            if (count == 0)
            {
                session.Flush();
                session = null;
            }
            tx.Complete();
        }

        public void rollbackTransaction()
        {
            count = 0;
            session = null;
        }
    }

Вспомогательный класс используется только в сервисах и не в хранилище Пример использования хелпера в сервисе:

public void updateCategory(CategoryDto category_dto)
{
 try
   {
    using (TransactionScope tx = transactionScopeHelper.getTransactionScope())
     {
      //works here
      transactionScopeHelper.complete(tx);
     }
   }
   catch(Exception)
   {
    transactionScopeHelper.rollbackTransaction();
    throw;
    }
}

Пример функции в хранилище :

 public T getById(long id)
 {
  ISession session = SessionFactory.OpenSession;
  return session.Get<T>(id);
 }

Всякий раз, когда я обновляю некоторую сущность , старые данные показываются после нескольких обновлений и снова после некоторого обновления, новые данные извлекаются. Это почти непрерывно. Почему я получаю эту проблему? Любая помощь будет оценена.

1 Ответ

0 голосов
/ 19 сентября 2018

Здесь происходит так много «необычных» вещей, что я едва знаю, с чего начать.

SessionFactory

Фабрика сессий NHibernate обычно инициализируется ОДИН РАЗ при запуске приложения (или когда первыйнеобходимо), а затем этот экземпляр будет жить в течение всей программы и будет использоваться всеми потоками.Обычно мы не ожидаем иметь отдельный экземпляр для потока (как это делает ThreadStatic).Повторная его инициализация приведет к серьезному снижению производительности .

buildSessionFactory () удалит сессию, если она есть, но не получит этот код, если сессия не пуста, поэтому яне понимаю, что на самом деле здесь происходит.

В конце buildSessionFactory (), iSessionFactory.OpenSession () вызывается дважды!Одного должно быть достаточно.

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

Сессия должна быть в конечном итоге удалена.Поэтому вызов метода с именем, подобным OpenSession, подразумевает, что мы получаем новый сеанс, который мы несем ответственность за закрытие.Но ваш собственный OpenSession () может возвращать один и тот же сеанс много раз, что затрудняет понимание того, кто именно отвечает за его закрытие.Лучше назвать его CurrentSession или аналогичным.

TransactionScopeHelper

Это также невозможно понять.Существует ссылка на переменную session, но определение и настройка этой переменной не показаны.Код неполный.В некоторых точках ссылка на сеанс устанавливается равной нулю, но попытки ее удаления не предпринимаются, что является обязательным.

Вызов Clear () для сеанса удалит все состояние из сеанса и заставит NHibernate потерять всезагруженные объекты и, следовательно, не смогут выполнять грязную проверку и сохраняться автоматически.Другой код должен был бы помнить, чтобы аккуратно заново все добавить.

Код не показывает, как и когда фактически создаются сеанс, транзакция и область транзакции.Невозможно сказать, правильны ли взаимодействия.Знает ли сессия даже объем транзакции?

Наконец, чтобы ответить на ваш вопрос: «Почему у меня возникает эта проблема?»

Ну, извините, но вся ситуация выглядит так.как беспорядокИ грязный код равен грязным результатам.Если, конечно, проблемы, о которых я упоминал выше, возникают из-за частичного копирования-вставки, в котором пропущены важные части.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...