Nhibernate事务已成功提交,但查询结果仍然是未修改的值

问题描述 投票:0回答:1

执行以下服务器代码,然后检查数据库中的升级表和任务表。相关字段已正确更新,表明事务已成功提交。

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);

因此,我修改了第一段代码并显式调用了update方法(请参阅注释中的代码),这次一切正常。

我的猜测是Nhibernate的缓存导致了上述问题。我使用syscache2管理二级缓存,该缓存设置为ReadWrite,然后使用sessionFacotry.getCurrentSession来管理Nhibernate的会话。

希望有人可以帮助我解释它的工作原理。

nhibernate transactions second-level-cache
1个回答
0
投票

您首先执行查询session.Get<Task>(taskId);。这会将实体加载到一级缓存中。

然后在您的交易中,您Get Promotion实体。 Task是它的IEnumerable属性。可能会出现延迟加载,您的foreach循环遍历ID为TasktaskID实体-对其进行修改-更新它-事务成功。由于所有这些都是在事务内发生的,因此session.Get<Task>(taskId);返回的初始实体不会更新。它仍然保留旧值。

然后,您再次在交易之外session.Query<Task>()。这次,NHibernate看到具有相同标识符的实体已经在会话缓存中加载了(使用session.Get<Task>(taskId);查询),它没有再次加载该实体,它只是返回了已经在会话缓存中的实体。由于该实体保留旧值,因此您会看到问题。

要确认这一点,请将所有这些查询放入事务块中并检查结果。或者,适当地管理session的范围。

了解您的ISession是您的Unit Of Work;仔细确定范围。

© www.soinside.com 2019 - 2024. All rights reserved.