Как обойти несколько соединений с базой данных внутри TransactionScope, если MSDTC отключен?
У меня есть веб-приложение, которое выдает запросы к 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 «RequNew»Моя третья попытка в списке выглядит примерно так:
public void LogSomethingInLogDatabase()
{
using (var transaction =
new TransactionScope(TransactionScopeOption.RequiresNew))
{
//do some database work
transaction.Complete();
}
}
И на самом деле, третье, что я попробовал, заставило работать модульные тесты, но все транзакции, которые завершились, поразили мою базу данных! Так что это был полный провал, поскольку весь смысл в том, чтобы НЕ влиять на мою базу данных.
Поэтому мой вопрос заключается в том, какие еще варианты существуют для достижения того, что я пытаюсь сделать, учитывая ограничения, которые я изложил?
РЕДАКТИРОВАТЬ:
Вот как будет выглядеть // // работа с базой данных
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();
}
}
}