为何NHibernate通过存储过程更新后无法反映内存状态?
这个问题我之前也踩过坑!核心原因其实是NHibernate的一级缓存(也就是Session级缓存)在作祟——哪怕你没配置二级缓存或查询缓存,Session本身会默认保留它加载过的所有实体快照。当你用存储过程直接修改数据库后,Session根本不知道数据已经发生了变化,后续用QueryOver查询时,它会直接从一级缓存里取旧数据,而不是去数据库拉最新的。
下面给你几个可行的解决方案,你可以根据自己的业务场景选择:
方案1:清空整个Session缓存
如果你在更新完成后,不需要再用到Session里之前加载的其他实体,可以直接调用:session.Clear();这会把Session中所有缓存的实体都移除,之后再用
QueryOver查询时,就会重新从数据库读取最新数据。不过要注意,这个操作会清除Session的所有持久化上下文,如果你之后还要操作之前加载的实体,可能会出现游离态的问题。方案2:移除单个实体的缓存
如果只是需要更新特定的实体,可以在遍历执行存储过程后,对每个实体调用:session.Evict(yourEntity);这样只会把当前实体从Session缓存中移除,不影响其他实体。后续查询该实体时,就会从数据库获取最新值。
方案3:主动刷新实体状态
如果你需要保留实体在Session中的关联状态,不想移除它,可以调用:session.Refresh(yourEntity);这个方法会主动从数据库拉取该实体的最新数据,更新Session缓存中的快照,这样后续查询就能拿到更新后的值了。
额外说明:关于
SetCacheMode
你之前试过的SetCacheMode()对一级缓存是无效的,这个配置主要是控制二级缓存和查询缓存的行为,所以不管怎么设置都不会影响Session本身的缓存。
总结一下:因为存储过程是绕开NHibernate的持久化上下文直接操作数据库的,所以Session的缓存不会自动同步这些变更,必须手动干预缓存来让后续查询拿到最新数据。
内容的提问来源于stack exchange,提问作者marcusstarnes

