Инструкция 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();
        }
    }
когда я запускаю тест, я получаю следующую ошибку:

сообщение результата: метод теста Проект.Хранилище.Unit-тестов.Покотест.TestBasicOperations бросил исключение: система.Данные.В sqlclient.SqlException: создание базы данных оператор не допускается в пределах мульти-оператора торговая операция.

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;
        }
}

почему это происходит?

также-если это имеет значение-ошибка не возникает, если я комментирую строку AddItem в TestMethod.

5 ответов


вы также можете использовать db.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, sqlCommand);

см.https://stackoverflow.com/a/24344654/375114 для деталей


в случае, если кто-то еще сталкивается с этой проблемой:

в моем классе репозитория у меня есть другое определение того, что обычно называется "dbContext" - ProjectDataSource. Это означает, что один контекст был создан в моем тестовом классе, а другой-в моем объекте репозитория. Отправка 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();
        }

для вашей информации эта ошибка возникает по дизайну, и это происходит всякий раз, когда не transactionable команды, выданный Microsoft SQL Server в рамках активной транзакции.

поэтому решение заключается в том, что


вы не можете использовать неявные коммиты вокруг определенных команд SQL. Примером может служить создание и удаление баз данных SQL server сделает автофиксации

см. раздел Примечания в справке MS SQL. http://msdn.microsoft.com/en-us/library/ms176061.aspx

и что-то на Auto Commit для получения дополнительной информации... http://msdn.microsoft.com/en-us/library/ms187878%28v=sql.105%29


попробуйте этот код

using (TransactionScope ts = новый TransactionScope (TransactionScopeOption.Подавить))

{
var sqlCommand = строка.Формат ("создать базу данных [{0}]", " TempBackupDB"); _контекст.База данных.ExecuteSqlCommand (TransactionalBehavior.DoNotEnsureTransaction, sqlCommand);

ts.Complete();

}