TransactionScope + NHIbernate多个会话

时间:2017-08-24 12:16:37

标签: c# nhibernate transactionscope

我正在编写与数据库相关的测试,但是他们需要很长时间才能完成并且我试图加快它们的速度。

我目前的代码如下:

[TestClass]
public class TestClass
{
    private const string ConnectionString = "...";
    private const string TemplateDatabaseBackupPath = "...";

    [ClassInitialize]
    public static void ClassInitialize(TestContext context) {
        InitializeTestEnviroment(); // create & fill db, init internals

        using (SqlConnection connection = new SqlConnection(ConnectionString)) {
            connection.Open();
            using (SqlCommand command = connection.CreateCommand()) {
                command.CommandText = "BACKUP DATABASE [Testing] TO DISK = @path";
                command.Parameters.AddWithValue("path", TemplateDatabaseBackupPath);
                command.ExecuteNonQuery();
            }
        }
    }

    [TestCleanup]
    public static void TestCleanup() {
        using (SqlConnection connection = new SqlConnection(ConnectionString)) {
            connection.Open();

            using (SqlCommand command = connection.CreateCommand()) {
                command.CommandText = "ALTER DATABASE [Testing] SET SINGLE_USER WITH ROLLBACK IMMEDIATE";
                command.ExecuteNonQuery();
            }

            using (SqlCommand command = connection.CreateCommand()) {
                command.CommandText = @"RESTORE DATABASE [Testing] FROM DISK = @path WITH REPLACE";
                command.Parameters.AddWithValue("path", TemplateDatabaseBackupPath);
                command.ExecuteNonQuery();
            }
        }
    }

    [TestMethod]
    public void TestMethod() {
         Entity entity = new Entity { Name = "Fred Flindstone" };
         BlackBox.UpdateEntity(entity, 42);

         Entity actual = BlackBox.GetEntityById(42);
         Assert.AreEqual("Fred Flindstone", actual.Name);
    }

    [TestMethod]
    public void TestMethod2() {
         Entity entity = new Entity { Name = "Fred Flindstone" };
         BlackBox.UpdateEntity(entity, 42); // 42 = entity id

         Entity actual = BlackBox.GetEntityById(42);
         Assert.AreEqual("Fred Flindstone", actual.Name);
    }
}

// NH mapping class
public class Entity {
    public int Id;
    public string Name;
}

// Not real code - just to get the idea how CRUD are performed internally,  this code cannot be easily changed (no unit tests for it)
public static class BlackBox {
    public static void UpdateEntity(object entity, int id) {
        using(var s = GetSession()){
            s.Update(id, entity);
        }
    }

    public static void GetEntityById(int id) {
        using(var s = GetSession()){
            return s.Session.Query<Entity>().Single(o => o.Id == Id);
        }
    }

    private static IHiberSession GetSession(){ 
        return ...; // not relevant
    }

    public interface IHiberSession {
        ISession Session { get; }
        ...
    }
}

经过一些调查后我发现了这个:

ClassInitialize                8s
TestMethod and TestMethod2     ~20ms
TestCleanup                    3s

显然我想减少TestCleanup的时间......

经过一番搜索,我找到了System.Transactions.TransactionScope并认为我有一个胜利者:

[ClassInitialize]
public static void ClassInitialize(TestContext context) {
    InitializeTestEnviroment();
}

[TestInitialize]
public static void TestInitialize() {
    _Scope = new System.Transactions.TransactionScope();
}

[TestCleanup]
public static void TestCleanup() {
    _Scope.Dispose(); // Rollback any changes made by test
}

应该比数据库恢复更快但不幸的是 我在会话Close()方法

期间得到此异常
System.InvalidOperationException: Disconnect cannot be called while a transaction is in progress.

似乎与这个封闭的问题有关:NH-1744但是这不会给我任何想法,请修改我的代码:(

无论如何,我的问题是如何让这段代码起作用:

void TestMethod() {
    using(var scope = new System.Transactions.TransactionScope()) {

        // these two usings cannot be changed ...
        using (ISession session = GetSession()) {
             // some CRUD
        }

        using (ISession session = GetSession()) {
            // some more CRUD
        }
    }
}

或任何其他想法,如何使数据库快速备份/恢复? (内存中备份会很好)

PS:TransactionScope仅用于单元测试,&#39; live&#39;代码是无范围的

感谢您的帮助......

0 个答案:

没有答案