Как использовать вложенные TransactionScopes для базы данных Azure SQL

В настоящее время я пытаюсь использовать вложенные области транзакций для доступа к БД по базе данных Azure SQL.

Я использую следующий код (.Net 4.5.1, мой код полностью асинхронный, ASP.Net MVC с EF6.1):

public async Task Test()
{
    // In my actual code, the DbContext is injected within the constructor
    // of my ASP.Net MVC Controller (thanks to IoC and dependency injection)
    // The same DbContext instance is used for the whole HttpRequest
    var context = new TestContext();

    using (var t1 = StartTransactionForAsync())
    {
        using (var t2 = StartTransactionForAsync())
        {
            context.Users.Add(new User { Name = Guid.NewGuid().ToString() });
            await context.SaveChangesAsync();

            t2.Complete();
        }
        ... // Some more code here
        t1.Complete();
    }
}

private static TransactionScope StartTransactionForAsync()
{
    return new TransactionScope(
        TransactionScopeOption.Required,
        new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted },
        TransactionScopeAsyncFlowOption.Enabled);
}

Все в порядке, за исключением того, что TransactionScope эскалируется в MSDTC, который (очевидно) не поддерживается Azure SQL Database. Поэтому я иногда получаю следующую ошибку:

Доступ к сети для Диспетчера распределенных транзакций (MSDTC) был отключен. Включите DTC для доступа к сети в безопасности конфигурации для MSDTC с использованием администраторов служб компонентов инструмент.

Я мог бы добавить Enlist=False в мою строку соединения, но он сломал бы код выше, поскольку внутренняя транзакция все равно будет вставляться в базу данных, даже если внешний TransactionScope располагается без Complete.

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

Итак, мои вопросы:

  • - это вложенные транзакции, поддерживаемые Azure SQL Database вообще?
  • почему приведенный выше код иногда перерастает в MSDTC?

Официальная документация гласит:

База данных Microsoft Azure SQL не поддерживает распределенные транзакции, которые являются транзакциями, которые влияют на несколько ресурсов. Дополнительные сведения см. В разделе Распределенные транзакции (ADO.NET).

Начиная с версии 2.0, транзакции приложения могут быть автоматически продвигается к распределенным транзакциям. Это относится к приложения, использующие класс System.Data.SqlClient для выполнения операции базы данных в контексте System.Transactions сделка.

Продвижение транзакций происходит, когда вы открываете несколько подключений к различных серверов или баз данных в TransactionScope или когда вы зачислить несколько подключений в объекте System.Transactions, используя метод EnlistTransaction. Продвижение транзакций также происходит, когда вы открываете несколько одновременных подключений к одному и тому же серверу и базы данных либо в пределах одного TransactionScope, либо с помощью Метод EnlistTransaction.

Начиная с версии 3.5, транзакция не будет повышаться, если строки подключения для параллельных соединений - это точно одна и та же. Для получения дополнительной информации о транзакциях и избежании транзакций продвижение по службе, см. Интеграция System.Transactions с SQL Server (ADO.NET).

который не отвечает ни на один из моих вопросов.

Ответ 2

MSDN: Продвижение транзакции в DTC может происходить, когда соединение закрывается и снова открывается в рамках одной транзакции. Поскольку Entity Framework открывает и закрывает соединение автоматически, вы должны вручную открыть и закрыть соединение, чтобы избежать продвижения транзакции.

Чтобы избежать этого сценария: Как вручную открыть соединение из контекста объекта

Ответ 3

База данных Azure SQL теперь поддерживает продвижение транзакции к распределенной транзакции из TransactionScope. Это теперь позволяет использовать TransactionScope там, где это было ранее невозможно, поскольку MSDTC не поддерживался. В результате вам необязательно контролировать подключение и закрывать соединение, как было предложено в предыдущем ответе. Смотрите: https://azure.microsoft.com/en-us/documentation/articles/sql-database-elastic-transactions-overview/.

Также обратите внимание, что Azure DB в настоящее время по-прежнему не полностью поддерживает несколько активных наборов результатов.