Nhibernate事务已经提交成功,但是查询的结果还是未修改的值
The Nhibernate transaction has been successfully committed, but the result of the query is still the unmodified value
执行以下服务器代码,然后查看数据库中的推广table和任务table。相关字段已正确更新,说明交易提交成功
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的session
希望有人能帮我解释一下这是如何工作的。
您先执行查询 session.Get<Task>(taskId);
。这会在一级缓存中加载实体。
然后在您的交易中,您 Get
Promotion
实体。 Task
就是它的IEnumerable
属性。由于可能是延迟加载,您的 foreach
循环遍历 ID 为 taskID
的 Task
实体 - 修改它 - 更新它 - 交易成功。由于所有这些都发生在事务内部,因此 session.Get<Task>(taskId);
返回的初始实体不会更新。它仍然保持旧值。
那么,你又在session.Query<Task>()
外交易了。这一次,NHibernate 看到具有相同标识符的实体已经加载到会话缓存中(使用 session.Get<Task>(taskId);
查询),它不会再次加载该实体,它只是 returns 已经在会话缓存中的实体。由于该实体持有旧值,您会发现问题所在。
为了确认这一点,将所有这些查询放入事务块中并检查结果。
或者,适当管理 session
的范围。
明白你的ISession
就是你的;仔细确定范围。
执行以下服务器代码,然后查看数据库中的推广table和任务table。相关字段已正确更新,说明交易提交成功
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的session
希望有人能帮我解释一下这是如何工作的。
您先执行查询 session.Get<Task>(taskId);
。这会在一级缓存中加载实体。
然后在您的交易中,您 Get
Promotion
实体。 Task
就是它的IEnumerable
属性。由于可能是延迟加载,您的 foreach
循环遍历 ID 为 taskID
的 Task
实体 - 修改它 - 更新它 - 交易成功。由于所有这些都发生在事务内部,因此 session.Get<Task>(taskId);
返回的初始实体不会更新。它仍然保持旧值。
那么,你又在session.Query<Task>()
外交易了。这一次,NHibernate 看到具有相同标识符的实体已经加载到会话缓存中(使用 session.Get<Task>(taskId);
查询),它不会再次加载该实体,它只是 returns 已经在会话缓存中的实体。由于该实体持有旧值,您会发现问题所在。
为了确认这一点,将所有这些查询放入事务块中并检查结果。
或者,适当管理 session
的范围。
明白你的ISession
就是你的