nhibernate是否应该在“SaveOrUpdate”后明确刷新会话?

我写了一个失败的集成测试:

    [Test]
    public void Find_WorkItemWithMatchingDescriptionExistsInRepository_ReturnsWorkItem()
    {
        // arrange
        WorkItemRepository repository = new WorkItemRepository(IsolatingFactory);

        const string Description = "A";
        WorkItem itemWithMatchingDescription = WorkItem.Create(1, Description);
        repository.Commit(itemWithMatchingDescription);

        // act
        List<WorkItem> searchResult = repository.Find(Description);

        // assert
        CollectionAssert.Contains(searchResult, itemWithMatchingDescription);
    }

在观察nhibernate的sql输出时,我注意到它为repository.Find()操作创建了一个select语句,但在select之前没有插入操作。 如果我在repository.Commit之后放置一个明确的session.Flush(),它按预期工作,但我发现这种行为很奇怪。 为什么在挂起插入和针对会话执行查询时,nhibernate不会自动刷新会话?

我在文档中找到了这个:

9.6。 红晕

有时,ISession将执行将ADO.NET连接的状态与内存中的对象状态同步所需的SQL语句。 这个过程,刷新,默认情况下发生在以下几点

* from some invocations of Find() or Enumerable()
* from NHibernate.ITransaction.Commit()
* from ISession.Flush() 

它看起来像默认的nhibernate行为是在find查询之前刷新。 我的存储库使用Ling来查询规范nhibernate,也许这是一个错误。

更新

如果我改变我的映射:

    public WorkItemClassMap()
    {
        Not.LazyLoad();

        Id(wi => wi.Id).GeneratedBy.Assigned();
        Map(wi => wi.Description).Length(500);
        Version(wi => wi.LastChanged).UnsavedValue(new DateTime().ToString());
    }

至:

    public WorkItemClassMap()
    {
        Not.LazyLoad();

        Id(wi => wi.Id).GeneratedBy.Identity();
        Map(wi => wi.Description).Length(500);
    }

它按预期工作(在执行查询之前,nhibernate会将插入刷新到数据库)。 我看不到这种行为的任何好理由,所以我假设它有一个错误。 看起来像在我的存储库查询之前需要手动刷新,这并不是我真正想做的事情。


您的示例中的WorkItem是否使用复合ID映射? 我刚刚编写了一个简单的测试。 当我拥有单个标识列时,我的虚拟类将自动刷新。 我用复合ID编写了相同的测试,并获得了上面描述的行为。


您应该为插入和选择方法使用不同的ISession实例。 如果这些会话位于using块中,以便它们在数据库事务中正确处理并处理,那么最好:

using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
    // perform your insert here
    tx.Commit();
}

假定您的资源库枯萎或创建一个已经存在的会话。 当您制作WorkItem并提交它时,它只会列出该会话要执行的作业列表。 如果你的仓库没有创建一个事务,而你的commit方法没有明确地提交这个事务。 然后,更新或保存将等待直到会话关闭,因此虽然您可以看到您创建的对象,但是直到您关闭会话或清除会话之前,您将无法获得范围标识。 当然searchResult不会知道任何关于你创建的对象而没有刷新或关闭事务。

交易中存在与交易一样的风险,但如果您正在创建新对象,则应该使用明确的交易。 NHProfiler会很乐意提醒你。

链接地址: http://www.djcxy.com/p/23231.html

上一篇: nhibernate should i flush session explicitly after "SaveOrUpdate"?

下一篇: NHibernate ISession Flush: Where and when to use it, and why?