nhibernate我应该在“之后显式刷新会话吗?”;保存或更新;?

nhibernate我应该在“之后显式刷新会话吗?”;保存或更新;?,nhibernate,session,Nhibernate,Session,我编写了一个失败的integrationtest: [Test] public void Find_WorkItemWithMatchingDescriptionExistsInRepository_ReturnsWorkItem() { // arrange WorkItemRepository repository = new WorkItemRepository(IsolatingFactory); const st

我编写了一个失败的integrationtest:

    [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行为是在通过find查询之前刷新。我的存储库使用Ling-to-nhibernate作为查询规范,也许这是一个bug

更新

如果我从以下位置更改映射:

    public WorkItemClassMap()
    {
        Not.LazyLoad();

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


它按预期工作(nhibernate在执行查询之前将插入刷新到数据库)。我看不出这种行为有什么好的理由,所以我假设它是一个bug。在查询我的存储库之前,似乎需要手动刷新,这不是我真正想要做的。

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

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

假设您的存储库wither创建或接受一个已经存在的会话。当您创建并提交WorkItem时,它会出现在该会话要执行的作业列表中。如果存储库未创建事务,并且提交方法未明确提交事务。然后更新或保存将等待会话关闭,因此,尽管您可以看到您创建的对象,但在关闭会话或刷新它之前,您将无法获取范围标识。当然,在没有刷新或关闭事务的情况下,searchResult对您创建的对象一无所知


一般来说,与会话相同的事务存在风险,但如果您正在创建新对象,则应该使用显式事务。NHProfiler会随时提醒您这一点。

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

我使用显式事务,整个集成测试在单个会话/事务中运行。我仍然没有找到一个很好的理由来解释为什么nhibernate在执行查询时不自动刷新。是的,我并不是说它是理想的,我昨天发现了它,当时我刚刚添加了一个子对象(在父对象上称为session.update),但对象的id还没有设置。这看起来很奇怪,但就像我说的,NHProfiler会提醒你这一点。我选择让我的存储库接口公开在当前会话上开始和提交事务的方法,这样理论上我就不必依赖于nhibernate。干杯,马克,我不喜欢这个约束。创建一个事务并在同一事务中执行读写操作应该是完全可以接受的。这是可以接受的。重要的是为每个工作单元创建并提交
ITransaction
。不管怎么说,你都应该这样做,就像文件上说的,它会自动引起潮红。嗯,这让我头疼。我只是对代码进行了重构,这样就可以明确地启动事务,并为每个工作单元提交事务。现在,如果在我创建一个新的工作单元时已经存在一个工作单元(这意味着该工作单元将共享同一个会话,但两者都将调用session.BeginTransaction()),那么如果外部工作单元在内部工作单元完成事务后尝试回滚,我会收到一个错误(尽管双方都请求了自己的事务)。听起来像是您的存储库。提交实际上并没有提交ITransaction。是吗?不,不是吗?我的存储库(不知道)不负责提交事务,因为它没有启动事务(但相信我,有一个事务:-)你肯定了解了一些事情。我不使用复合键,但主键已分配,我还使用了一个版本字段。如果我删除了版本字段,并将主键更改为ex“Generated by Identity”,它将按预期工作,这一定是一个bug。
    public WorkItemClassMap()
    {
        Not.LazyLoad();

        Id(wi => wi.Id).GeneratedBy.Identity();
        Map(wi => wi.Description).Length(500);
    }
using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
    // perform your insert here
    tx.Commit();
}