2013-03-01 83 views
9

我试图建立一个快速测试,在每次运行时删除并重新创建一个数据库。我有以下几点:在多语句事务中不允许CREATE DATABASE语句

[TestClass] 
public class PocoTest 
{ 
    private TransactionScope _transactionScope; 
    private ProjectDataSource _dataSource; 
    private Repository _repository = new Repository(); 
    private const string _cstring = "Data Source=.;Initial Catalog=test_db;Trusted_Connection=True"; 

    [TestInitialize] 
    public virtual void TestInitialize() 
    { 
     _dataSource = new ProjectDataSource(_cstring); 
     _dataSource.Database.Delete(); 
     _dataSource.Database.CreateIfNotExists(); 
     _transactionScope = new TransactionScope(); 
    } 
    [TestMethod] 
    public void TestBasicOperations() 
    {     
     var item = _repository.AddItem(new Item(){Details = "Test Item"}); 
     // AddItem makes a call through the data context to add a set and then calls datacontext.SaveChanges() 
    } 


    [TestCleanup] 
    public void TestCleanup() 
    { 
     // rollback 
     if (_transactionScope != null) 
     { 
      _transactionScope.Dispose(); 
     } 
    } 

然而,当我运行测试,我得到以下错误:

Result Message: Test method Project.Repository.UnitTests.PocoTest.TestBasicOperations threw exception: System.Data.SqlClient.SqlException: CREATE DATABASE statement not allowed within multi-statement transaction.

ProjectDataSource是在这里:

public class ProjectDataSource : DbContext, IProjectDataSource 
{ 

    public ProjectDataSource() : base("DefaultConnection") 
    { 

    } 

    public ProjectDataSource(string connectionString) : base(connectionString) 
    { 

    } 

    public DbSet<Set> Sets { get; set; } 
} 

库:

public class Repository : IRepository 
{ 
    private readonly ProjectDataSource _db = new ProjectDataSource(); 
    public Item AddItem(Item item) 
     { 
      _db.Items.Add(item); 
      _db.SaveChanges(); 
      return item; 
     } 
} 

这是怎么发生的?

另外 - 如果它有任何区别 - 如果我注释掉TestMethod中的AddItem行,则不会发生该错误。

回答

3

万一别人运行到这个问题:

在我的仓库类,我有什么常用贴上了“的DbContext”另一种定义 - ProjectDataSource。这意味着在我的测试类中创建了一个上下文,而在我的Repository对象中创建了另一个上下文。发送ConnectionString,以我的回购类解决了这个问题:

在库:

public class Repository : IRepository 
    { 
     private readonly ProjectDataSource _db; 

     public Repository(string connectionString) 
     { 
      _db = new ProjectDataSource(connectionString); 
     } 

     public Repository() 
     { 
      _db = new ProjectDataSource(); 
     } 

从我的测试:

private TransactionScope _transactionScope; 
     private Repository _repository; 
     private ProjectDataSource _dataSource; 
     private const string _connectionString = "Data Source=.;Initial Catalog=test_db;Trusted_Connection=True"; 

     [TestInitialize] 
     public virtual void TestInitialize() 
     { 
      _repository = new Repository(_connectionString); 
      _dataSource = new ProjectDataSource(_connectionString); 
      _dataSource.Database.Delete(); 
      _dataSource.Database.CreateIfNotExists(); 
      _transactionScope = new TransactionScope(); 
     } 
+0

我不完全明白为什么会造成此问题。 您是否在说创建2个等价的dbcontext实例会导致问题。这意味着应用程序中只能存在一个到特定数据库的dbcontext? – 2016-03-08 09:28:24

+0

Eran Otzap,我知道这是一个迟到的问题,但是今天面对这个问题,我认为发表一个解释根本原因的答案会很有帮助。希望能帮助到你。 – 2016-11-07 22:09:40

4

您还可以使用db.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, sqlCommand);

https://stackoverflow.com/a/24344654/375114的细节

+0

的确帮助了我,谢谢你 – 2016-12-29 06:45:07

2

为了您的信息,通过设计出现此错误它发生在每当不可交易的命令发布到Microsoft SQL Server内一个交易。

因此,该解决方案授予Database.CreateIfNotExists()不受任何事务作用域的影响。请记住,SQL Profiler是你的朋友。

您可以获得大致updated list of commands that are not allowed to run whithin transactions

注意:如果有人想知道为什么我要提供基于Sybase产品的列表,请记住Microsoft SQL Server与Sybase的引擎共享其大部分基本遗传。如需进一步阅读,请参阅https://en.wikipedia.org/wiki/Microsoft_SQL_Server