2009-10-09 2 views
6

Ist es möglich, das System.Transactions-Programmiermodell ohne Unterstützung für verteilte Transaktionen zu verwenden?.NET: Wie kann die Werbung in System.Transactions deaktiviert werden?

so etwas wie

TransactionConfig.DisablePromotion = true; 
+0

Welches Problem haben Sie, dass Sie Promotion deaktivieren möchten? –

+0

Ich verwende einen Verbindungsserver, um zwei SQL Server zu verbinden. Für die Linked-Server-Logik habe ich explizite Transaktionen verwendet, daher ist die Integrität in Ordnung. Aber wenn ich mit dem Verbindungsserver fertig bin, gibt SQL Server die interne Verbindung nicht frei. Wenn meine Anwendung weiterläuft und implizite Transaktionen verwendet (zur Vereinfachung), werden sie immer gegen EINE Datenbank ausgeführt. Die Heraufstufung erfolgt jedoch, da die Verbindung zum verbundenen Server noch offen ist. – andreas

Antwort

10

Nein, Sie können die Transaktionsaktion über eine Eigenschaft oder Konfiguration nicht deaktivieren. Die einzige Möglichkeit, die Transaktionsaktion zu deaktivieren, besteht darin, die Bedingungen zu vermeiden, die dazu führen, dass die Transaktion zu einer verteilten Transaktion heraufgestuft wird.

Um transaction management escalation zu vermeiden Sie müssen:

  • SQL Server 2005 oder höher als Ihrer Datenbank haben

  • wenn SQL Server 2005, verwenden Sie nur eine Datenbankverbindung für die Lebensdauer der Transaktion . (SQL Server 2008 ermöglicht es Ihnen, mehrere Verbindungen innerhalb einer Transaktion ohne Förderung auftritt. Verwenden)

  • nur Zugriff auf eine Datenbank

  • nicht Ihre Transaktion über Anwendungsdomänen

passieren


Der Grund für die Regeln ist, die ACID properties der Transaktion sicherzustellen. Als Beispiel nehmen wir an, dass Sie angeben könnten, um eine Transaktion nicht zu fördern (wie in Ihrem Code-Snippet), aber Ihr Code greift auf zwei Datenbanken zu (ich weiß - Ihr Code verwendet nur eine Datenbank). Sie haben jetzt angegeben, dass Sie keine Transaktionen verwenden dürfen, Sie haben eine Transaktion gestartet und Sie haben angegeben, dass zwei Datenbanken innerhalb dieser Einheit arbeiten sollen. Es besteht ein Konflikt zwischen den ACID-Eigenschaften der Transaktion und dem Wunsch, eine verteilte Transaktion zu vermeiden. Es scheint mir, dass es zwei Möglichkeiten geben würde, dies zu handhaben: entweder die Transaktion zu einer verteilten Transaktion zu fördern (was Sie sagten, dass Sie nicht wollten!) Oder eine Ausnahme auslösen (da Sie die Integrität der Transaktion).

Die Verwendung einer DisablePromotion-Eigenschaft hätte also keinen großen Wert, da die Anwendung die Transaktion nicht vorantreiben muss, um die Eskalationsregeln zu befolgen.

Wenn Sie wirklich wollten, könnten Sie das Ereignis DistributedTransactionStarted behandeln und eine Ausnahme auslösen, wenn eine verteilte Transaktion gestartet wird. Das würde garantieren, dass Ihre Anwendung keine verteilten Transaktionen verwendet, aber das ist wahrscheinlich nicht das, was Sie wollen.

+2

+1 für Sie Tuzo. Gut gesagt. –

+1

Wenn Ihre Transaktion hochgestuft wird, weil Sie auf zwei Datenbanken zugreifen, Sie aber nur * in eine Datenbank schreiben, ist es möglich, die Hochstufung zu vermeiden, indem Sie die Transaktion beim Zugriff auf die andere Datenbank unterdrücken. d.h. 'using (new TransactionScope (TransactionScopeOption.Suppress, neue TransactionOptions {IsolationLevel = IsolationLevel.ReadUncommitted})) {// Zugriff auf andere db}' –

2

Ich glaube nicht, dass es eine direkte Art und Weise Förderung zu deaktivieren ist. Möglicherweise möchten Sie sich die Situationen ansehen, in denen eine Transaktion gefördert wird. Juval Lowy schrieb eine ausgezeichnete whitepaper (auch herunterladbar here) alles über System.Transactions. Er behandelt die Promotionsregeln im Detail.

+0

Sie können auch eine HTML-Version von Juval Lowy Introducing System.Transactions finden Sie unter http://msdn.microsoft.com/en-us/library/ms973865.aspx –

+0

Ausgezeichnetes Whitepaper. Vielen Dank. – Maarten

1

Ich verwende den folgenden Code mit deaktiviertem MSDTC-Dienst.

var txOpts = new TransactionOptions 
      { 
      IsolationLevel = IsolationLevel.ReadCommitted, 
      Timeout = TimeSpan.FromMinutes(10)}; 

using (var tx = new TransactionScope(TransactionScopeOption.Suppress, txOpts)) 
{ 
    using (var db1 = new ObjectContext(connection1)) 
    { 
    db1.Connection.Open(); 
    using (var db1tx = db1.Connection.BeginTransaction(
           System.Data.IsolationLevel.ReadCommitted)) 
    { 
     using (var db2 = new ObjectContext(connection2)) 
     { 
     db2.Connection.Open(); 
     using (var db2tx = db2.Connection.BeginTransaction(
          System.Data.IsolationLevel.ReadCommitted)) 
     { 
      // do stuff 

      db1.SaveChanges(false); 
      db2.SaveChanges(false); 

      db1tx.Commit(); 
      db2tx.Commit(); 
      tx.Complete(); 
     } 
     } 
    } 
    } 
}