TransactionScope и DataContext - PullRequest
       16

TransactionScope и DataContext

2 голосов
/ 26 ноября 2010

Я понимаю, что этот вопрос задавался ранее, но мне еще не удалось найти ответ, который действительно работает.

Моя проблема возникает, когда мои модульные тесты пытаются вызвать веб-сервис, который использует Linq длязапрос к базе данных.

Модульный тест настроен так:

[TestInitialize]
public void SetUp()
{
    var scope = new TransactionScope(TransactionScopeOption.Required,TimeSpan.MaxValue);
    var database = new DatabaseDataContext();
}

[TestCleanup]
public void TearDown()
{
    scope.Dispose();
    database.Dispose();
}

[TestMethod]
public void GetCategoryList_Success()
{
    // create test data
    var result = service.GetItems();
}

Метод service.GetItems выглядит так:

try
{
    using (DatabaseDataContext database = new DatabaseDataContext())
    {
        var items = (from i in database.Items
                    select i).ToList<Items>();
        return items;
    }
}
catch (Exception ex)
{
   // log error
   return null;
}

Когда запрос Linqпытается выполнить, выдается следующее исключение:

Операция недопустима для состояния транзакции.

Я считаю, что это связано с вложенными транзакциями,но мне нужно держать транзакцию в тестовом классе открытой, чтобы тестовые данные фактически не сохранялись в базе данных, и я могу распоряжаться ими после запуска теста.

Кроме того, мой хостинг находится на общем ресурсеНапример, я не могу внести какие-либо изменения непосредственно на сервер.

Есть ли способ заставить это работать как есть, или, альтернативно, есть ли альтернатива использованию TransactionScope в этом контексте?

1 Ответ

0 голосов
/ 26 ноября 2010

Вы пытаетесь создать два подключения к одной и той же базе данных в одной TransactionScope - одно подключение для процесса тестирования, а другое - для процесса веб-службы.Это не работает, потому что в базе данных не могут быть вложены переходы из разных процессов.

Вам следует изменить свой подход к тестированию здесь.Прочитайте ответ Яна.

В качестве обходного пути вы можете заставить свой веб-сервис управлять транзакцией.Метод, скажем, BeginGlobalTran должен создать глобальный объект Transaction (или TransactionScope) для веб-службы (хранится в свойстве), все другие его методы должны использовать этот объект (поэтому все другие транзакции вложены в «глобальную» транзакцию), другой метод говорит: RollbackGlobalTran должен откатить эту «глобальную» транзакцию.
При этом это обходной путь, и он может вызвать некоторые неожиданные побочные эффекты (например, ошибка в методе вызовет 'глобальная транзакция недоступна, поэтому вам придется перезапустить ее, чтобы избежать дальнейших ошибок).

...