Транзакция Nhibernate была успешно зафиксирована, но результатом запроса остается неизменное значение - PullRequest
0 голосов
/ 24 марта 2020

Выполните следующий код сервера, а затем проверьте таблицу повышения и таблицу задач в базе данных. Связанные поля были обновлены правильно, что указывает на то, что транзакция была успешно зафиксирована.

using (ITransaction tx = session.BeginTransaction())
{
    try
    {
        Promotion p = session.Get<Promotion>(request.PromotionId);
        p.Status = PromotionStatus.Canceled;
        foreach (Task task in p.Tasks)
        {
            if (task.AnnounceStatus == TaskAnnounceStatus.New)
            {
                task.AnnounceStatus = TaskAnnounceStatus.PromotionCanceled;
                task.CancelTime = DateTime.Now;
                //session.Update(task);
            }
        }
        tx.Commit();
    }   
    catch
    {
        tx.Rollback();
        throw;
    }
}

Затем выполните следующий запрос (запрос A), полученные данные также являются обновленным значением. Похоже, что все очень хорошо.

tasks = session.Query<Task>().Where(p => p.AnnounceStatus == Model.TaskAnnounceStatus.New && p.ProcessStatus == Model.TaskProcessStatus.New).ToList();

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

Task task = session.Get<Task>(taskId);

Поэтому я изменил первый фрагмент кода и явно вызвал метод обновления (см. Код в комментарии), и на этот раз все работало нормально.

Я предполагаю, что кеш Nhibernate вызывает вышеуказанную проблему. Я использую syscache2 для управления кешем второго уровня, для кеша было установлено значение ReadWrite, а для управления сессией Nhibernate использую sessionFacotry.getCurrentSession.

Надеюсь, кто-то может помочь мне объяснить, как это работает.

1 Ответ

0 голосов
/ 25 марта 2020

Сначала вы выполняете запрос session.Get<Task>(taskId);. Это загружает сущность в кэш первого уровня.

Затем в вашей транзакции вы Get сущность Promotion. Task - это свойство IEnumerable. Какая бы ленивая загрузка ни была, ваша foreach l oop итерация по сущности Task с идентификатором taskID - изменяет ее - обновляет - транзакция выполнена успешно. Поскольку все это происходит внутри транзакции, ваша первоначальная сущность, возвращаемая session.Get<Task>(taskId);, не обновляется. Он по-прежнему содержит старые значения.

Затем вы снова session.Query<Task>() вне транзакции. На этот раз NHibernate видит, что объект с таким же идентификатором уже загружен в кэш сеанса (с запросом session.Get<Task>(taskId);), он не загружает этот объект снова, он просто возвращает объект уже в кеше сеанса. Поскольку эта сущность содержит старые значения, вы видите проблему.

Чтобы подтвердить это, поместите все эти запросы в блок транзакции и проверьте результат.
В качестве альтернативы управляйте так, чтобы область действия session была правильной.

Поймите, что ваша ISession - это ваша Единица работы ; осторожно оцените это.

...