NHibernate FlushMode查找前自动不刷新
好的,我已经看到一些帖子询问几乎相同的内容,但要点有所不同.
All right, I've seen some posts asking almost the same thing but the points were a little bit different.
这是一个典型的案例:我正在保存/更新实体,并且在 SAME SESSION 中,我试图从数据库中获取它们(使用条件/查找/枚举/等),且FlushMode = Auto.问题是: NHibernate在查询之前不会刷新更新,所以我从数据库中获取不一致的数据.
This is a classic case: I'm saving/updating an entity and, within the SAME SESSION, I'm trying to get them from the database (using criteria/find/enumerable/etc) with FlushMode = Auto. The matter is: NHibernate isn't flushing the updates before querying, so I'm getting inconsistent data from the database.
足够好",如文档所述:
"Fair enough", some people will say, as the documentation states:
默认情况下,在以下几点发生此刷新过程:
This process, flush, occurs by default at the following points:
- 来自Find()或Enumerable()的一些调用
- 来自NHibernate.ITransaction.Commit()
- 来自ISession.Flush()
- from some invocations of Find() or Enumerable()
- from NHibernate.ITransaction.Commit()
- from ISession.Flush()
大胆的某些引用"清楚地表明NH完全不承担任何责任. IMO,但是,我们在这里存在一个一致性问题,因为该文档还指出:
The bold "some invocations" clearly says that NH has no responsibility at all. IMO, though, we have a consistency problem here because the doc also states that:
除非显式地使用Flush(),否则绝对不能保证Session在何时执行ADO.NET调用,仅保证它们执行的顺序.但是, NHibernate确实保证了ISession.Find(..)方法将永远不会返回过时的数据.他们也不会返回错误的数据.
因此,如果我使用CreateQuery(查找替换)并筛选属性值为Value = 20的实体,则NH可能不返回值为Value = 30的实体,对吗?但是实际上就是这样,因为刷新不会在应有的时候自动发生.
So, if I'm using CreateQuery (Find replacement) and filtering for entities with property Value = 20, NH may NOT return entities with Value = 30, right? But that's what happens in fact, because the Flush is not happening automatically when it should.
public void FlushModeAutoTest()
{
ISession session = _sessionFactory.OpenSession();
session.FlushMode = FlushMode.Auto;
MappedEntity entity = new MappedEntity() { Name = "Entity", Value = 20 };
session.Save(entity);
entity.Value = 30;
session.SaveOrUpdate(entity);
// RETURNS ONE ENTITY, WHEN SHOULD RETURN ZERO
var list = session.CreateQuery("from MappedEntity where Value = 20").List<MappedEntity>();
session.Flush();
session.Close();
}
毕竟:我理解错了吗,是错误还是仅仅是无法预测的功能,所以每个人都必须致电Flush来确保其工作正常?
After all: am I getting it wrong, is it a bug or simply a non predictable feature so everybody have to call Flush to assure its work?
谢谢.
Filipe
我不太熟悉NHibernate源代码,但是2.1.2.GA版本中ISession实现中的此方法可能会回答以下问题:>
I'm not very familiar with the NHibernate source code but this method from the ISession implementation in the 2.1.2.GA release may answer the question:
/// <summary>
/// detect in-memory changes, determine if the changes are to tables
/// named in the query and, if so, complete execution the flush
/// </summary>
/// <param name="querySpaces"></param>
/// <returns></returns>
private bool AutoFlushIfRequired(ISet<string> querySpaces)
{
using (new SessionIdLoggingContext(SessionId))
{
CheckAndUpdateSessionStatus();
if (!TransactionInProgress)
{
// do not auto-flush while outside a transaction
return false;
}
AutoFlushEvent autoFlushEvent = new AutoFlushEvent(querySpaces, this);
IAutoFlushEventListener[] autoFlushEventListener = listeners.AutoFlushEventListeners;
for (int i = 0; i < autoFlushEventListener.Length; i++)
{
autoFlushEventListener[i].OnAutoFlush(autoFlushEvent);
}
return autoFlushEvent.FlushRequired;
}
}
我的意思是,自动刷新将仅保证事务内部的一致性,这是有道理的.尝试使用事务重写您的测试,我很好奇这是否可以解决问题.
I take this to mean that auto flush will only guarantee consistency inside a transaction, which makes some sense. Try rewriting your test using a transaction, I'm very curious if that will fix the problem.