NHibernate查询返回尚未持久化到数据库的更改

NHibernate查询返回尚未持久化到数据库的更改,nhibernate,.net-3.5,Nhibernate,.net 3.5,下面的单元测试失败,我对检索到的对象进行了更改,然后在同一个会话中,我进行了一个查询,该查询似乎考虑了我对该对象所做的未限制更改 如何让NHibernate忽略任何未限制的更改而只查询数据库 [Test] public void Test() { // Arrange Area area1 = new Area { Name = "Area 1" }; Area area2 = new Area { Name = "Area 2" }; using (ISessi

下面的单元测试失败,我对检索到的对象进行了更改,然后在同一个会话中,我进行了一个查询,该查询似乎考虑了我对该对象所做的未限制更改

如何让NHibernate忽略任何未限制的更改而只查询数据库

[Test]
public void Test()
{
    // Arrange
    Area area1 = new Area { Name = "Area 1" };
    Area area2 = new Area { Name = "Area 2" };
    using (ISession session = SessionFactory.OpenSession())
    {
        using (var transaction = session.BeginTransaction())
        {
            session.Save(area1);
            session.Save(area2);
            transaction.Commit();
        }
    }
    int resultCount;

    // Act
    using (ISession session = SessionFactory.OpenSession())
    {
        Area existingArea;
        using (var transaction = session.BeginTransaction())
        {
            existingArea = session.Get<Area>(area1.ID);
        }

        existingArea.Name = area2.Name;

        using (var transaction = session.BeginTransaction())
        {
            resultCount = session.CreateCriteria<Area>().Add(Restrictions.Eq("Name", existingArea.Name)).List<Area>().Count;
        }
    }

    // Assert
    Assert.AreEqual(1, resultCount);
}
[测试]
公开无效测试()
{
//安排
Area area1=新区域{Name=“Area 1”};
Area Area 2=新区域{Name=“Area 2”};
使用(ISession session=SessionFactory.OpenSession())
{
使用(var transaction=session.BeginTransaction())
{
会话。保存(区域1);
会话保存(区域2);
Commit();
}
}
int-resultCount;
//表演
使用(ISession session=SessionFactory.OpenSession())
{
现有面积;
使用(var transaction=session.BeginTransaction())
{
existingArea=session.Get(area1.ID);
}
existingArea.Name=area2.Name;
使用(var transaction=session.BeginTransaction())
{
resultCount=session.CreateCriteria().Add(Restrictions.Eq(“Name”,existingArea.Name)).List().Count;
}
}
//断言
Assert.AreEqual(1,resultCount);
}

您在会话中所做的所有更改在整个会话中都是持久的。因此,在会话中,无法知道会话早期更改了哪些数据,以及哪些数据与数据库模式匹配

您可以尝试通过打开两个不同的会话来解决此问题。在其中一种情况下,不要做任何改变,然后你就会知道你从什么开始


…或者,如果应用程序中存在需要跟踪历史记录的特定点,我将创建某种历史记录表,您可以在其中保存对要跟踪的特定项目的每次更改。我认为这个解决方案是最好的,但话说回来,这完全取决于您的具体需求。

您在会话中所做的所有更改在整个会话中都是持久的。因此,在会话中,无法知道会话早期更改了哪些数据,以及哪些数据与数据库模式匹配

您可以尝试通过打开两个不同的会话来解决此问题。在其中一种情况下,不要做任何改变,然后你就会知道你从什么开始


…或者,如果应用程序中存在需要跟踪历史记录的特定点,我将创建某种历史记录表,您可以在其中保存对要跟踪的特定项目的每次更改。我认为这个解决方案是最好的,但话说回来,这完全取决于您的具体需求。

我找到了我需要的:

session.FlushMode = FlushMode.Commit;
导致此问题的原因是,默认FlushMode(FlushMode.Auto)有时会在查询之前刷新对数据库的更改,以防止过时读取。 通过更改为FlushMode.Commit,它仅在调用Commit时将更改写入数据库,这符合我的需要


谢谢你的帮助gillyb。

我找到了我需要的东西:

session.FlushMode = FlushMode.Commit;
导致此问题的原因是,默认FlushMode(FlushMode.Auto)有时会在查询之前刷新对数据库的更改,以防止过时读取。 通过更改为FlushMode.Commit,它仅在调用Commit时将更改写入数据库,这符合我的需要


感谢您的帮助gillyb。

感谢您的回复,我正在ASP.NET应用程序中使用此功能,每个请求打开一个会话。参考代码示例,我获取existingArea,然后将表单元素中的值读入其中。然后我执行一个查询,以确保我没有将该值更改为与任何其他区域冲突的任何值(名称必须是唯一的)。多个会话不是一个选项,也没有必要进行历史记录跟踪(至少在这种情况下不是这样)。我并不特别需要知道会话中发生了什么变化,我只需要直接查询数据库。我不确定我是否理解正确-但也许你可以将Area对象克隆到一个新对象,然后在对其进行更改时,可以将更改后的对象与更改前的克隆对象进行比较。如果您在Area对象上实现IClonable和IComparable,那么在整个代码中这将非常容易。感谢您的回复,我正在ASP.NET应用程序中使用它,并且我会为每个请求打开一个会话。参考代码示例,我获取existingArea,然后将表单元素中的值读入其中。然后我执行一个查询,以确保我没有将该值更改为与任何其他区域冲突的任何值(名称必须是唯一的)。多个会话不是一个选项,也没有必要进行历史记录跟踪(至少在这种情况下不是这样)。我并不特别需要知道会话中发生了什么变化,我只需要直接查询数据库。我不确定我是否理解正确-但也许你可以将Area对象克隆到一个新对象,然后在对其进行更改时,可以将更改后的对象与更改前的克隆对象进行比较。如果您在Area对象上实现IClonable和IComparable,那么在整个代码中这将非常容易做到。(+1)让我向您表示感谢!我也不知道这一点,我相信这将有助于我将来了解这一点。我在Visual Studio中键入“会话”,然后滚动自动完成列表,查找突出的内容。正在阅读FlushMode.Auto的帮助文本工具提示。(+1)让我向您表示感谢!我也不知道这一点,我相信这将有助于我将来了解这一点。我在Visual Studio中键入“会话”,然后滚动自动完成列表,查找突出的内容。正在阅读FlushMode.Auto的帮助文本工具提示。