2013-03-01 3 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; } 
} 

Repository:

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.

ответ

3

В случае, если кто-то работает в этот вопрос:

В моем Repository классе, у меня есть другое определение, что обычно помечены «DbContext» - ProjectDataSource. Это означает, что в моем тестовом классе был создан один контекст, а другой - в моем объекте репозитория. Отправка ConnectionString моего класса репо решить эту проблему:

В Repository:

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 для конкретного db? –

+0

Эран Отзап, я знаю, что это поздно, но, столкнувшись с этим вопросом сегодня, я подумал, что было бы полезно опубликовать ответ, объясняющий коренные причины. Надеюсь, поможет. –

1

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

Смотрите раздел замечания в справке 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

4

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

См https://stackoverflow.com/a/24344654/375114 подробности

+0

помог мне поблагодарить вас –

2

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

Решение поэтому предоставляет то, что 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

Смежные вопросы