У меня есть веб-приложение, которое выдает запросы к 3 базам данных в DAL. Я пишу несколько интеграционных тестов, чтобы удостовериться, что общая функциональность в обоих направлениях действительно выполняет то, что я ожидаю. Это полностью отделено от моих юнит-тестов, просто к вашему сведению.
То, как я намеревался написать эти тесты, было чем-то вроде этого
[Test]
public void WorkflowExampleTest()
{
(using var transaction = new TransactionScope())
{
Presenter.ProcessWorkflow();
}
}
В этом случае ведущий уже настроен. Проблема возникает в методе ProcessWorkflow, потому что он вызывает различные репозитории, которые в свою очередь обращаются к разным базам данных, и на моем сервере sql не включен MSDTC, поэтому я получаю сообщение об ошибке всякий раз, когда пытаюсь создать новое соединение SQL или изменить базу данных кэшированного соединения на другую.
Для краткости ведущий напоминает что-то вроде:
public void ProcessWorkflow()
{
LogRepository.LogSomethingInLogDatabase();
var l_results = ProcessRepository.DoSomeWorkOnProcessDatabase();
ResultsRepository.IssueResultstoResultsDatabase(l_results);
}
Я пытался решить эту проблему множеством вещей.
- Кэширование одного активного соединения постоянно и изменение целевой базы данных
- Кэширование одного активного соединения для каждой целевой базы данных (это было бесполезно, потому что пул должен был сделать это для меня, но я хотел посмотреть, получаю ли я другие результаты)
- Добавление дополнительных TransactionScopes внутри каждого репозитория, чтобы у них были свои собственные транзакции, используя TransactionScopeOption «requireNew»
Моя третья попытка в списке выглядит примерно так:
public void LogSomethingInLogDatabase()
{
using (var transaction =
new TransactionScope(TransactionScopeOption.RequiresNew))
{
//do some database work
transaction.Complete();
}
}
И на самом деле третье, что я попробовал, фактически заставило работать модульные тесты, но все транзакции, которые завершили, на самом деле попадают в мою базу данных! Так что это был полный провал, поскольку весь смысл в том, чтобы НЕ влиять на мою базу данных.
Поэтому мой вопрос: какие еще варианты существуют для достижения того, что я пытаюсь сделать, учитывая ограничения, которые я наложил?
EDIT:
Вот как бы "// выполнить работу с базой данных" было бы похоже
using (var l_context = new DataContext(TargetDatabaseEnum.SomeDatabase))
{
//use a SqlCommand here
//use a SqlDataAdapter inside the SqlCommand
//etc.
}
и сам DataContext выглядит примерно так
public class DataContext : IDisposable
{
static int References { get; set; }
static SqlConnection Connection { get; set; }
TargetDatabaseEnum OriginalDatabase { get; set; }
public DataContext(TargetDatabaseEnum database)
{
if (Connection == null)
Connection = new SqlConnection();
if (Connection.Database != DatabaseInfo.GetDatabaseName(database))
{
OriginalDatabase =
DatabaseInfo.GetDatabaseEnum(Connection.Database);
Connection.ChangeDatabase(
DatabaseInfo.GetDatabaseName(database));
}
if (Connection.State == ConnectionState.Closed)
{
Connection.Open() //<- ERROR HAPPENS HERE
}
ConnectionReferences++;
}
public void Dispose()
{
if (Connection.State == ConnectionState.Open)
{
Connection.ChangeDatabase(
DatabaseInfo.GetDatabaseName(OriginalDatabase));
}
if (Connection != null && --ConnectionReferences <= 0)
{
if (Connection.State == ConnectionState.Open)
Connection.Close();
Connection.Dispose();
}
}
}