我想对我在NHibernate(NB.我使用 NHibernate 2.1.2)
情况是这样的
//STATEFULL SESSION
var session = sessionFactory.OpenSession()
using(var transaction = session.BeginTransaction()){
var entity = new MyEntityType();
entity.Id = 1;
session.Save(entity);
var entity2 = session.Get<MyEntityType>(1);
//OK! It returns saved entity...as I expect
transaction.Commit();
}
但。。。在无状态会话上,行为会发生变化...
//STATELESS SESSION
var session = sessionFactory.OpenStatelessSession()
using(var transaction = session.BeginTransaction()){
var entity = new MyEntityType();
entity.Id = 1;
session.Insert(entity);
var entity2 = session.Get<MyEntityType>(1);
//entity2 IS NULL!!! Why?
transaction.Commit();
}
我的问题是...如何检查我是否已在无状态会话的事务范围内插入了项目?
嗯,无状态是...无 国籍。因此,没有会话缓存可用于从内存中返回插入的实体。
现在,为什么它没有在数据库中被读取?因为它还没有!
很可能已启用批处理(adonet.batch_size
xml 配置参数,或通过代码Environment.BatchSize
配置属性,或者在会话工厂级别启用批处理时未通过IStatelessSession.SetBatchSize(int)
禁用批处理)。启用批处理后,如果 NHibernate 数据库驱动程序支持它,DML 操作将尽可能一起批处理,直至达到配置的批大小,然后刷新到数据库。
因此,可能会发生与无状态会话的此类刷新:
- 如果达到要执行的操作的"批量大小"计数。
- 如果事务已提交。
- 如果完成另一个 DML 查询,不仅其参数值不同。
(在您的情况下,例如在插入后插入另一种实体,或者在插入后更新或删除任何类型的实体。 - 通过显式刷新批处理器,点击内部会话界面。
s.GetSessionImplementation().Flush();
如果要将Insert
立即发送到数据库,请禁用批处理。将其设置为0
将禁用它。
但是,为什么首先要使用无状态会话?可能以有效的方式插入大量实体。在这种情况下,禁用批处理将值得您的目的。
因此,您可以改为访问由会话GetSessionImplementation()
方法公开的内部会话接口,并显式Flush
它。但是,直接调用内部可能会产生未定义的行为,因此这不是推荐的做法。