NHibernate FlushMode自动不会在查找之前刷新

jfn*_*eis 6 nhibernate

好吧,我看到一些帖子几乎要问同样的事情但是点数有点不同.

这是一个经典案例:我正在保存/更新一个实体,并且在同一个会话中,我试图通过FlushMode = Auto从数据库中获取它们(使用criteria/find/enumerable/etc).问题是:NHibernate在查询之前没有刷新更新,所以我从数据库中获取了不一致的数据.

有些人会说,"足够公平",正如文件所述:

此过程刷新默认情况下发生在以下几点:

  • 来自Find()或Enumerable()的一些调用
  • 来自NHibernate.ITransaction.Commit()
  • 来自ISession.Flush()

大胆的"一些调用"清楚地表明NH根本没有责任.但是,IMO在这里遇到了一致性问题,因为该文档还指出:

除非明确表示Flush(),否则绝对无法保证Session何时执行ADO.NET调用,只保证执行它们的顺序.但是,NHibernate确保ISession.Find(..)方法永远不会返回陈旧数据; 他们也不会返回错误的数据.

因此,如果我使用CreateQuery(查找替换)并过滤属性值为20的实体,NH可能不会返回值为30的实体,对吧?但这就是事实上发生的事情,因为Flush不应该自动发生.

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();
}
Run Code Online (Sandbox Code Playgroud)

毕竟:我错了,它是一个错误还是一个不可预测的功能所以每个人都必须打电话给Flush以确保它的工作?

谢谢.

菲利佩

Jam*_*Ide 8

我对NHibernate源代码不是很熟悉,但2.1.2.GA版本中ISession实现的这个方法可能会回答这个问题:

/// <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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为这意味着自动刷新只能保证事务内部的一致性,这是有道理的.尝试使用事务重写您的测试,我很好奇,如果这将解决问题.