Ich versuche derzeit verschachtelte Transaktionsbereiche für den DB-Zugriff auf eine Azure SQL-Datenbank zu verwenden.So verwenden Sie geschachtelte TransactionScopes für eine Azure SQL-Datenbank
Ich verwende den folgenden Code (.Net 4.5.1, meinen Code async ganzen Weg nach unten, dann ist es ASP.Net MVC mit 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);
}
Alles in Ordnung, außer manchmal eskaliert die TransactionScope
zu MSDTC, die (offensichtlich) nicht von Azure SQL-Datenbank unterstützt wird. So bekomme ich manchmal die folgende Fehlermeldung:
Network access for Distributed Transaction Manager (MSDTC) has been disabled. Please enable DTC for network access in the security configuration for MSDTC using the Component Services Administrative tool.
ich Enlist=False
meiner Verbindungszeichenfolge hinzufügen könnte, aber es würde den Code oben brechen, da die innere Transaktion noch in die Datenbank einfügen würde, selbst wenn der äußere TransactionScope
ohne Complete
angeordnet ist, .
Ich bin eine einzige Datenbank Targeting, einen einzelnen Entity Framework Kontext für meinen ganzen HttpRequest
, immer mit der gleichen Verbindungszeichenfolge verwenden.
Also meine Fragen sind:
- sind verschachtelte Transaktionen an allen von Azure SQL-Datenbank unterstützt?
- Warum eskaliert der obige Code manchmal zu MSDTC?
The official documentation sagt:
Microsoft Azure SQL Database does not support distributed transactions, which are transactions that affect several resources. For more information, see Distributed Transactions (ADO.NET).
Starting with the version 2.0, application transactions may be automatically promoted to distributed transactions. This applies to applications that use the System.Data.SqlClient class to perform database operations in the context of a System.Transactions transaction.
Transaction promotion occurs when you open multiple connections to different servers or databases within a TransactionScope, or when you enlist multiple connections in a System.Transactions object by using the EnlistTransaction method. Transaction promotion also occurs when you open multiple concurrent connections to the same server and database either within the same TransactionScope or by using the EnlistTransaction method.
Starting with the version 3.5, the transaction will not be promoted if the connection strings for the concurrent connections are exactly the same. For more information about transactions and avoiding transaction promotion, see System.Transactions Integration with SQL Server (ADO.NET).
, die keine meiner Fragen beantwortet.
TransactionScope wurde für * implizite/automatische * Transaktion (unter Ausnutzung des MSDTC-Dienstes) erfunden, nicht für * verschachtelte * Transaktionen. Es scheint, dass Sie diese Begriffe verwirren.Eskalation zu DTC ist wahrscheinlich passiert, weil Sie etwas Async-Zeug haben (was verschiedene Threads bedeutet, was wahrscheinlich unterschiedliche Verbindungen bedeutet). Ich sehe kaum, warum du asynchrone Sachen in diese Art von (Server?) Code schreiben willst - jenseits der aktuellen Mode um "Async" :-). Mehr zur Eskalation hier: http://stackoverflow.com/questions/1690892/transactionscope-automatisch-escaling-to-msdtc-on-some-machines –
@SimonMourier Ich bin mir nicht sicher, ob ich deinen ersten Satz verstehe; 'TransactionScope' unterstützt definitiv verschachtelte Transaktionen (siehe zum Beispiel http://stackoverflow.com/a/2742025/870604). Durch das Rollback des Root-Bereichs sollte die gesamte Operation zurückgesetzt werden. Was das Async betrifft, benutze ich es aus Gründen der Skalierbarkeit/Performance. Das ändert nichts an der Tatsache, dass selbst wenn die beiden Operationen auf zwei verschiedenen Threads ausgeführt werden, sie immer noch dieselbe DB-Verbindung verwenden (eine eindeutige DbContext-Instanz wird verwendet). – ken2k
Ich habe nie gesagt, TS unterstützt verschachtelte Transaktionen nicht. Ich sagte, du verwirrst beide Begriffe. Verschachtelte Transaktionen existierten lange bevor DTC existierte. Sie können verschachtelte Transaktionen ohne TS durchführen, aber Sie sprechen von geschachtelten * Bereichen *. Async bringt hier keinen Skalierbarkeitsvorteil, wenn Sie hinter der Szene auf einer einzigen Verbindung serialisieren (es ist in der Tat wahrscheinlich schlimmer), was ich immer noch bezweifle. IMHO sollten Sie einen vollständigen Repro-Code zeigen, um wilde Vermutungen zu vermeiden. –