Как использовать вложенные 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).
который не отвечает ни на один из моих вопросов.
Ответы
Ответ 1
Попробуйте добавить это в свою строку подключения, включив Несколько активных наборов результатов. Это должно остановить проблему MSDTC; хотя я не уверен в этом.
MultipleActiveResultSets=True;
При дополнительной информации вложенная транзакция не является вложенной транзакцией.
Ответ 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 в настоящее время по-прежнему не полностью поддерживает несколько активных наборов результатов.