如何使Nhibernate不将对象中的更改持久化到数据库

如何使Nhibernate不将对象中的更改持久化到数据库,nhibernate,Nhibernate,在运行集成测试的数据库中有一组数据。为了防止数据库中的NHibernate持久化对象修改,实现了从DefaultSaveOrUpdateEventListener继承的EventListener 还有一种方法: public override void OnSaveOrUpdate(SaveOrUpdateEvent @event) { @event.Session.CancelQuery(); Trace.TraceWarning("NhibernateSaveUpdateCancel

在运行集成测试的数据库中有一组数据。为了防止数据库中的NHibernate持久化对象修改,实现了从DefaultSaveOrUpdateEventListener继承的EventListener

还有一种方法:

public override void OnSaveOrUpdate(SaveOrUpdateEvent @event)
{
  @event.Session.CancelQuery();
  Trace.TraceWarning("NhibernateSaveUpdateCanceler: Persistence will be ignored.");
}
不幸的是,这并不像预期的那样有效。因此,预期的行为是捕捉在数据库中写入更改的时刻,并以某种方式取消更改,尽管将对象保留为存在,以便可以验证对它们的修改

谢谢

编辑


无法执行此操作,因为测试方法中存在多个事务,因此通过持久化更改存在需求矛盾,因此一方的所有事务都可用,而另一方的更改不会持久化到数据库中。

当调用
session.Save
session.Update
。刷新更改时,将为每个实体调用FlusEntity事件。实现
iLushEntityEventListener

在调用
会话时调用Save或Update事件侦听器。Save
会话。Update
。刷新更改时,将为每个实体调用FlusEntity事件。实现
iLushEntityEventListener

使用集成测试夹具库重新编写集成测试。在基类中创建: 初始化nhibernate并创建会话工厂的装置设置 关闭会话工厂的夹具拆卸 创建会话和事务的测试设置 回滚事务并关闭会话的测试拆卸

像这样

[TestFixture]
public abstract class TestFixtureBase
{
    protected ISessionFactory SessionFactory { get; private set; }
    protected ISession Session { get; private set; }
    protected ITransaction Tx { get; private set; }

    [TestFixtureSetUp]
    public virtual void SetUp()
    {
        var nh = new NHInit();

        nh.Initialize();

        SessionFactory = nh.SessionFactory;
    }

    [TestFixtureTearDown]
    public virtual void TearDown()
    {
        SessionFactory.Close();
    }


    [SetUp]
    public void Test_Set_Up()
    {
        Session = SessionFactory.OpenSession();
        Tx = Session.BeginTransaction();
    }

    [TearDown]
    public void Test_tear_down()
    {
        Tx.Rollback();
        Tx.Dispose();
        Session.Close();
    }
}

然后编写测试。

使用集成测试夹具底座重新编写集成测试。在基类中创建: 初始化nhibernate并创建会话工厂的装置设置 关闭会话工厂的夹具拆卸 创建会话和事务的测试设置 回滚事务并关闭会话的测试拆卸

像这样

[TestFixture]
public abstract class TestFixtureBase
{
    protected ISessionFactory SessionFactory { get; private set; }
    protected ISession Session { get; private set; }
    protected ITransaction Tx { get; private set; }

    [TestFixtureSetUp]
    public virtual void SetUp()
    {
        var nh = new NHInit();

        nh.Initialize();

        SessionFactory = nh.SessionFactory;
    }

    [TestFixtureTearDown]
    public virtual void TearDown()
    {
        SessionFactory.Close();
    }


    [SetUp]
    public void Test_Set_Up()
    {
        Session = SessionFactory.OpenSession();
        Tx = Session.BeginTransaction();
    }

    [TearDown]
    public void Test_tear_down()
    {
        Tx.Rollback();
        Tx.Dispose();
        Session.Close();
    }
}

然后编写您的测试。

目的是进行集成测试,允许检查要修改的对象,但其更改不会反映在数据库中,从而允许在同一组数据上运行多个测试。。。。但是如何对多个事务运行测试呢?你在评论弗兰的回答时提到了这一点。这不行。更重要的是:在同一事务中,NH需要刷新更改以使后续查询正常工作。如果你抑制潮红,你会打破它的。斯蒂芬,你是对的。如果在另一个事务中使用临时对象,则数据库查询将返回旧数据,因此更改将丢失。我最终取消了test in TearDown方法引入的更改。我正在内存中的sqlite数据库上运行测试。它非常快。我为每个测试创建了一个全新的数据库。在测试过程中,您只需要保持一个连接处于打开状态,就可以使db保持活动状态。并且只创建一次会话工厂,因为这很慢。其目的是进行集成测试,允许检查对象进行修改,但其更改不会反映在数据库中,从而允许在同一组数据上运行多个测试。。。。但是如何对多个事务运行测试呢?你在评论弗兰的回答时提到了这一点。这不行。更重要的是:在同一事务中,NH需要刷新更改以使后续查询正常工作。如果你抑制潮红,你会打破它的。斯蒂芬,你是对的。如果在另一个事务中使用临时对象,则数据库查询将返回旧数据,因此更改将丢失。我最终取消了test in TearDown方法引入的更改。我正在内存中的sqlite数据库上运行测试。它非常快。我为每个测试创建了一个全新的数据库。在测试过程中,您只需要保持一个连接处于打开状态,就可以使db保持活动状态。只创建一次会话工厂,因为这很慢。不幸的是,我不能这样做,因为测试代码中有多个事务。虽然在测试较小的功能块时这是一个好主意。不幸的是,我不能这样做,因为测试代码中有多个事务。尽管在测试较小的功能块时,这是一个好主意。