HAVIT Knowledge Base

Vývoj webových aplikací, .NET, SQL, návrh
Welcome to HAVIT Knowledge Base Sign in | Join | Help
-
Home Články Forums Obrázky Soubory

.NET Framework

Microsoft .NET Framework, Base Class Library

System.Transactions - dobrý sluha, ale špatný pán

.NET Framework 2.0 zavádí nový namespace System.Transactions, který umožňuje velmi programátorsky pohodlnou práci s transakcemi, a to jako transakcemi ADO.NET/SQL Serveru, tak i MSMQ (Message Queues) a MSDTC (Distributed Transaction Coordinator).

Můžeme tak například celkem transparentně obalit kus kódu transakcí, aniž bychom museli do kódu zasahovat a transakce explicitně nastavovat. 

using (TransactionScope scope = new TransactionScope())
{
   using (SqlConnection connection = new SqlConnection(connectionString))
   {
      SqlCommand command = connection.CreateCommand();
      command.CommandText = "Insert....";
      command.Connection = connection;

      SqlCommand command2 = connection.CreateCommand();
      command2.CommandText = "Update....";
      command2.Connection = connection;

      connection.Open();
      command.ExecuteNonQuery();
      command2.ExecuteNonQuery();
      connection.Close();
   }
   scope.Complete();
}
...vše vypadá krásně a opravdu to může i krásně fungovat, můžeme si ale i pěkně naběhnout.

V první řadě, pokud výše uvedený kód běží vůči SQL2000 serveru, pak se namísto běžné SQL-transakce vytvoří distribuovaná transakce spravovaná MSDTC, Distributed Transaction Coordinatorem - což bude mít velmi nepříjemný dopad na výkon naší aplikace. Při použití s SQL2000 totiž nejsou podporovány tzv. "promotable transactions".

Pokud používáme SQL2005 server, tento problém odpadá, transakce bude realizována prostřednictvím SqlTransaction.

Dalším problémem však je, že explicitně neurčujeme, co vše je součástí transakce, takže veškeré transakční zdroje (resources), které v rámci transaction-scope používáme, se automaticky zaregistrují jako součást transakce a snadno tak opět skončíme na distribuované transakci spravované MSDTC.

Závěr

Osobně raději pro transakční zpracování SQL používám klasickou SqlTransaction, navíc pokud si vytvoříme malou pomůcku, pak můžeme i SqlTransaction řešit obdobně pohodlným způsobem:

int myID = 5;
object result;
 
SqlDataAccess.ExecuteTransaction(
   delegate(SqlTransaction transaction)
   {
      // uvnitř lze používat i lokální proměnné (samozřejmě i parametry, statické fieldy atp.)
 
      SqlCommand cmd1 = new SqlCommand("command string");
      cmd1.Transaction = transaction;
      cmd1.Connection = transaction.Connection;
      cmd1.Parameters.AddWithValue("@MyID", myID);
      cmd1.ExecuteNonQuery();
 
      SqlCommand cmd2 = new SqlCommand("another command");
      cmd2.Transaction = transaction;
      cmd2.Connection = transaction.Connection;
      result = cmd2.ExecuteScalar();
   });

Související články

Published 15. září 2006 16:04 by Robert Haken
Filed under:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

Tomas said:

Claenk mi temer mluvi z duse :-). Nejspis je to jen moji nezkusenosti s Transactions (parkrat jsem je rozhodne pouzival, ale expert nejsem) ze nedokazu tuhle novinku poradne ocenit.

Kazdopadne me neuveritelne znervoznuje kdyz v TransactionScope jasne nevidim kde se ta transakce vlastne pouziva - tim ze se to "udela samo" a nic se nikam nepreda jako parametr.

prosince 8, 2006 3:18

What do you think?

(required) 
(optional)
(required) 
Enter the code you see below

Submit