Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我可以刷新我的NHibernate会话并在不提交事务的情况下获得新会话吗?_Nhibernate_Testing_Castle Activerecord_Database Testing - Fatal编程技术网

我可以刷新我的NHibernate会话并在不提交事务的情况下获得新会话吗?

我可以刷新我的NHibernate会话并在不提交事务的情况下获得新会话吗?,nhibernate,testing,castle-activerecord,database-testing,Nhibernate,Testing,Castle Activerecord,Database Testing,我正在使用Castle ActiveRecord进行持久性测试,我正在尝试为我的持久性测试编写一个基类,它将执行以下操作: 为每个测试用例打开一个事务,并在测试用例结束时回滚它,这样我就可以为每个测试用例获得一个干净的DB,而不必为每个测试用例重建模式 提供了刷新我的NHiBalEnter会话并在测试中间获得一个新的会话的能力,这样我就知道我的持久操作真的命中了数据库而不是NHiBiess会话。 为了证明我的基类(ARTestBase)正在工作,我提出了以下示例测试 [TestFixture

我正在使用Castle ActiveRecord进行持久性测试,我正在尝试为我的持久性测试编写一个基类,它将执行以下操作:

  • 为每个测试用例打开一个事务,并在测试用例结束时回滚它,这样我就可以为每个测试用例获得一个干净的DB,而不必为每个测试用例重建模式
  • 提供了刷新我的NHiBalEnter会话并在测试中间获得一个新的会话的能力,这样我就知道我的持久操作真的命中了数据库而不是NHiBiess会话。
为了证明我的基类(
ARTestBase
)正在工作,我提出了以下示例测试

[TestFixture]
public class ARTestBaseTest : ARTestBase
{
    [Test]
    public void object_created_in_this_test_should_not_get_committed_to_db()
    {
        ActiveRecordMediator<Entity>.Save(new Entity {Name = "test"});

        Assert.That(ActiveRecordMediator<Entity>.Count(), Is.EqualTo(1));
    }

    [Test]
    public void object_created_in_previous_test_should_not_have_been_committed_to_db()
    {
        ActiveRecordMediator<Entity>.Save(new Entity {Name = "test"});

        Assert.That(ActiveRecordMediator<Entity>.Count(), Is.EqualTo(1));
    }

    [Test]
    public void calling_flush_should_make_nhibernate_retrieve_fresh_objects()
    {
        var savedEntity = new Entity {Name = "test"};
        ActiveRecordMediator<Entity>.Save(savedEntity);
        Flush();
        // Could use FindOne, but then this test would fail if the transactions aren't being rolled back
        foreach (var entity in ActiveRecordMediator<Entity>.FindAll())
        {
            Assert.That(entity, Is.Not.SameAs(savedEntity));
        }
    }
}
请注意,我使用的是带有内存数据库的自定义SQLite提供程序。我的自定义提供程序(取自)始终保持连接打开以维护架构。删除此项并使用常规SQL Server数据库不会改变行为


是否有办法实现所需的行为?

对ActiveRecord不太确定,但在NHibernate中,事务属于会话,而不是相反

如果您经常使用ADO.Net,这将更有意义,因为要创建
IDbTransaction
,您需要使用连接。ActiveRecord的
TransactionScope
(和NHiGenerate的
ITransaction
)本质上包装了一个
IDB事务
,因此您需要在
TransactionScope
之前创建
SessionScope

您还可能发现(取决于您使用的是NHibernate 1.2 GA还是NHibernate 2.*,以及
FlushMode
您的
SessionScope
所具有的功能)调用
FindAll()
可能会导致会话刷新,因为NHibernate将意识到,如果不执行最后一次调用
Save
,它将无法检索正确的数据


说了这么多,你是否尝试过使用
SessionScope.Flush()
而不是创建新的
SessionScope

使用
SessionScope.Flush()
会使我的第三次测试失败。据我所知,
Flush()
执行SQL将我的记录推入数据库,但不会从会话中逐出对象。这与您所说的导致刷新的
FindAll()
相符

我真正想要的是
SessionScope.Flush()
(将数据库的状态与会话同步)加上
SessionScope.executeAll()
(确保在后续查询中获得新对象)。我的
newsessionscope()
尝试模拟
executeall()

您对包含该事务的会话的评论,而不是相反,确实给了我一个想法。我不确定在
事务范围内创建一个新的
会话范围
,并期望它参与事务,这有多合乎礼仪,但它似乎起到了作用:

public abstract class ARTestBase
{
    private SessionScope sessionScope;
    private TransactionScope transactionScope;
    private bool reverse;
    private IList<SessionScope> undisposedScopes;

    [TestFixtureSetUp]
    public void InitialiseAR()
    {
        ActiveRecordStarter.ResetInitializationFlag();
        ActiveRecordStarter.Initialize(typeof (Entity).Assembly, ActiveRecordSectionHandler.Instance);
        ActiveRecordStarter.CreateSchema();
        InitialiseIoC();
        undisposedScopes = new List<SessionScope>();
    }

    [SetUp]
    public virtual void SetUp()
    {
        sessionScope = new SessionScope();
        transactionScope = new TransactionScope(OnDispose.Rollback);
        transactionScope.VoteRollBack();
        base.CreateInstanceUnderTest();
        reverse = false;
    }

    [TearDown]
    public virtual void TearDown()
    {
        if (reverse)
        {
            sessionScope.Dispose();
            transactionScope.Dispose();
        }
        else
        {
            transactionScope.Dispose();
            sessionScope.Dispose();
        }
    }

    [TestFixtureTearDown]
    public virtual void TestFixtureTearDown()
    {
        foreach (var scope in undisposedScopes)
        {
            scope.Dispose();
        }
        SQLiteProvider.ExplicitlyDestroyConnection();
    }

    protected void Flush()
    {
        reverse = true;
        sessionScope.Flush();
        undisposedScopes.Add(sessionScope);
        sessionScope = new SessionScope();
    }
}
公共抽象类ARTestBase
{
非公开会议范围会议范围;
私人交易范围交易范围;
私有布尔反转;
私人IList未分解示波器;
[TestFixtureSetUp]
公共无效初始值()
{
ActiveRecordStarter.ResetInitializationFlag();
初始化(typeof(Entity.Assembly,ActiveRecordSectionHandler.Instance);
ActiveRecordStarter.CreateSchema();
InitialiseIoC();
undisposedScopes=新列表();
}
[设置]
公共虚拟空间设置()
{
sessionScope=新sessionScope();
transactionScope=新transactionScope(OnDispose.Rollback);
transactionScope.voterrollback();
base.CreateInstanceUnderTest();
反向=假;
}
[撕裂]
公共虚拟void拆卸()
{
如果(反向)
{
sessionScope.Dispose();
transactionScope.Dispose();
}
其他的
{
transactionScope.Dispose();
sessionScope.Dispose();
}
}
[测试固定器拆卸]
公共虚拟void TestFixtureTearDown()
{
foreach(undisposedScopes中的var范围)
{
scope.Dispose();
}
SQLiteProvider.ExplicitlyDestroyConnection();
}
受保护的空刷新()
{
反向=真;
sessionScope.Flush();
添加(会话范围);
sessionScope=新sessionScope();
}
}
进一步考虑,这将不允许您在每个测试用例中刷新超过一次。我想我可以通过更仔细地跟踪示波器来处理这个问题。我可能以后再调查

public abstract class ARTestBase
{
    private SessionScope sessionScope;
    private TransactionScope transactionScope;
    private bool reverse;
    private IList<SessionScope> undisposedScopes;

    [TestFixtureSetUp]
    public void InitialiseAR()
    {
        ActiveRecordStarter.ResetInitializationFlag();
        ActiveRecordStarter.Initialize(typeof (Entity).Assembly, ActiveRecordSectionHandler.Instance);
        ActiveRecordStarter.CreateSchema();
        InitialiseIoC();
        undisposedScopes = new List<SessionScope>();
    }

    [SetUp]
    public virtual void SetUp()
    {
        sessionScope = new SessionScope();
        transactionScope = new TransactionScope(OnDispose.Rollback);
        transactionScope.VoteRollBack();
        base.CreateInstanceUnderTest();
        reverse = false;
    }

    [TearDown]
    public virtual void TearDown()
    {
        if (reverse)
        {
            sessionScope.Dispose();
            transactionScope.Dispose();
        }
        else
        {
            transactionScope.Dispose();
            sessionScope.Dispose();
        }
    }

    [TestFixtureTearDown]
    public virtual void TestFixtureTearDown()
    {
        foreach (var scope in undisposedScopes)
        {
            scope.Dispose();
        }
        SQLiteProvider.ExplicitlyDestroyConnection();
    }

    protected void Flush()
    {
        reverse = true;
        sessionScope.Flush();
        undisposedScopes.Add(sessionScope);
        sessionScope = new SessionScope();
    }
}