У меня есть веб-приложение, которое выдает запросы к 3 базам данных в DAL. Я пишу некоторые интеграционные тесты, чтобы убедиться, что общая функциональность в оба конца фактически делает то, что я ожидаю от нее. Это полностью отличается от моих модульных тестов, просто fyi.
То, как я собирался писать эти тесты, было чем-то вроде этого
[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 "RequiresNew"
Моя третья попытка в списке выглядит примерно так:
public void LogSomethingInLogDatabase()
{
using (var transaction =
new TransactionScope(TransactionScopeOption.RequiresNew))
{
//do some database work
transaction.Complete();
}
}
И на самом деле 3-я вещь, которую я пробовал, фактически заставила модульные тесты работать, но все транзакции, которые завершили фактически HIT мою базу данных! Так что это был полный провал, так как все дело в том, чтобы НЕ воздействовать на мою базу данных.
Таким образом, мой вопрос заключается в том, какие другие варианты существуют для выполнения того, что я пытаюсь сделать, учитывая ограничения, которые я изложил?
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();
}
}
}