Sql-Server

不能在使用者事務中使用 DROP DATABASE 語句

  • April 6, 2016

不確定這個問題是否屬於這裡,但我希望有人可以幫助我。

我已經將集成測試一直深入到數據庫(使用 mssql localDB)。我希望每個測試都使用自己的數據獨立執行 - 我想在每個測試執行之前用我的假數據重新填充數據庫。我試圖通過交易來實現它,但沒有成功。這是我嘗試將其拉下來的方法:

public class TestDbInitializer : DropCreateAlways<MyContext>()
{
   public static List<Item> Items;

   public override Seed(DbContext context)
   {
       Items = new List<Item>();

       // Adding items
       // .. 

       Items.ForEach(x => context.Add(x));

       context.SaveChanges();
   }
}


public class BaseTransactionsTests
{
   private TransactionScope _scope

   [TestInitialize]
   public void Initialize()
   {
       _scope = new TransactionScope();
   }

   [TestCleanup]
   public void Cleanup()
   {
       _scope.Dispose();
   }
}

[TestClass]
public class IntegrationTests : BaseTransactionsTests

private IDependenciesContainer _container;

public static void AssemblyInit(TestContext context)
{
   Database.SetInitializer(new TestDbInitializer());

   _container = new DependenciesContainer();

   // Registers all my application's dependencies
   _container.RegisterAll();
}

[TestInitialize]
public void Initialize()
{
   using (var context = new MyContext("TestsDatabase"))
   {
       context.Initialize(true);
   }
}

[TestMethod]
public void TestAddItem()
{
   var controller = _container.Resolve<MyController>();

   var result = controller.AddItem(new Item({Name = "Test"}))

   var goodResult = result as OkNegotiatedResult<string>();

   if (result == null)
       Assert.Fail("Bad result")

   using (var context = new MyContext("TestsDatabase"))
   {
       Assert.AreEqual(context.Items.Count, TestDbInitializer.Items.Count + 1)
   }
}

我在測試中使用我的依賴注入器,一次註冊所有依賴項(AssemblyInitialize)。

我創建了一個用於測試的數據庫實例,以及一個帶有假數據 Seed 方法的特定 DropCreateAlways 初始化程序,我也將其設置為 AssemblyInitialize 中的初始化程序。

我想在每次測試執行之前用我的假數據重新填充數據庫。對於那種情況,我實現了包含事務範圍的基類。

當我執行測試時,在 TestInitialize 中播種數據庫時會引發以下異常:

DROP DATABASE statement cannot be used inside a user transaction

我應該如何處理?此外,您如何看待我對這些集成測試的實現?有什麼可以改進的?

創建一個單獨的初始化程序,如果數據庫存在則刪除它,然後在任何事務處理程式碼之外創建數據庫。如果由於任何原因失敗,您可以(可能)立即使測試失敗並調查失敗的原因

來自MSDN

CREATE DATABASE 語句必須在自動送出模式(預設事務管理模式)下執行,並且不允許在顯式或隱式事務中執行。

如果需要,您可以為每個單獨的測試執行此操作:

  1. DROP DATABASE如果存在
  2. CREATE DATABASE
  3. 創建必要的 DDL
  4. 執行 DML 單元測試
  5. DROP DATABASE

但是,那將是矯枉過正。我只是在所有測試開始時創建數據庫,並在最後刪除它。每個單元測試都可以包裝在一個事務中,該事務要麼是回滾的,要麼是送出的,這取決於進一步測試的要求。

我尋找了一個資源來解釋為什麼 CREATE DATABASE不能在事務中使用,但我找不到。Kenneth Fisher提供了以下 TechNet 連結,其中顯示了在事務中不起作用的所有命令:

事務中允許的 Transact-SQL 語句

我們的猜測是,其中很多是不允許的,因為它們會影響文件系統,而文件系統不是事務性的。

引用自:https://dba.stackexchange.com/questions/134429