Инструкция 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();
}