System.Transactions is new to .NET 2.0 and it significantly improves support for distributed transactions. Please refer to the Microsoft documentation for detailed information about the System.Transactions namespace.
System.Transactions is flexible enough to handle both implicit and explicit transactions:
|

|
|
Implicit (automatic) transactions uses TransactionScope, and they are automatically managed by the infrastructure. It is recommended to use this model. |
|

|
|
Explicit transactions uses CommittableTransaction, and they need to be manually managed, i.e., they will need to be manually enlisted in a transaction context. |
 |
Please refer to System.Transactions Example (C#) to understand the differences when using System.Transactions as transaction boundary markers, while using the three different TransactionProviders, i.e., OpenAccess ORM (which is the default), Implicit (TransactionScope) and Explicit (CommittableTransaction). |
Implicit Transactions
Implicit Transactions, as mentioned above, are managed by the infrastructure, i.e. in this case you do not need to enlist resources explicitly with the transaction. The example given below shows a connection being made to a database followed by a OQL query being executed against it and then an object is modified, all wrapped within a transaction, i.e. the TransactionScope class:
| C# |
Copy Code |
|
static void TransactionScopeUsage() { Database database = Database.Get("DatabaseConnection1"); database.Properties.TransactionProvider = TransactionProvider.TransactionScope;
using (IObjectScope scope = database.GetObjectScope()) { // Transaction to modify object using (TransactionScope txnScop = new TransactionScope()) { foreach (Person p in scope .GetOqlQuery("select * from PersonExtent as x where x.name = 'Smith'") .Execute())
{ p.Name = "Miller"; }
txnScop.Complete(); } } } |
| VB.NET |
Copy Code |
|
Shared Sub TransactionScopeUsage() Dim database As Database = Database.[Get]("DatabaseConnection1") database.Properties.TransactionProvider = TransactionProvider.TransactionScope Using scope As IObjectScope = database.GetObjectScope() Using txnScop As New TransactionScope() For Each p As Person In scope.GetOqlQuery("select * from PersonExtent as x where x.name = 'Smith'").Execute() p.Name = "Miller" Next txnScop.Complete() End Using End Using End Sub |
In case of implicit transactions, once the connection is opened, the transaction gets automatically enlisted in the current transaction scope. That is, whenever a user invokes a method, like GetOQLQuery(), or tries to gain read/write access to a persistent field, the ObjectScope checks if there are any active transactions and if there are any it will participate in them, therefore the ObjectScope implicitly enlists the transaction.
Explicit Transactions
Explicit Transactions are useful when you want to make modifications to a transaction's behavior. In this case, you can manually create a transaction and then tell your connections to explicitly enlist in the transaction scope. The same example as mentioned above has been used here, however, this demonstrates explicit transactions, i.e., it uses the CommittableTransaction class:
| C# |
Copy Code |
|
static void ExplicitUsage() { Database database = Database.Get("DatabaseConnection1"); database.Properties.TransactionProvider = TransactionProvider.Explicit;
using (IObjectScope scope = database.GetObjectScope()) { // Transaction to modify object using (CommittableTransaction txn = new CommittableTransaction()) { // Enlisting the connection in the transaction scope scope.EnlistTransaction(txn);
foreach (Person p in scope .GetOqlQuery("select * from PersonExtent as x where x.name = 'Smith'") .Execute())
{ p.Name = "Miller"; }
txn.Commit(); } } } |
| VB.NET |
Copy Code |
|
Shared Sub ExplicitUsage() Dim database As Database = Database.[Get]("DatabaseConnection1") database.Properties.TransactionProvider = TransactionProvider.Explicit Using scope As IObjectScope = database.GetObjectScope() Using txn As New CommittableTransaction() scope.EnlistTransaction(txn) For Each p As Person In scope.GetOqlQuery("select * from PersonExtent as x where x.name = 'Smith'").Execute() p.Name = "Miller" Next txn.Commit() End Using End Using End Sub |
As you can see in case of explicit transactions, you need to manually enlist a connection into the transaction and then commit the transaction. That is, the ObjectScope needs to be explicitly told to work with or be connected to the transaction, by calling the EnlistTransaction() method.
 |
As shown in the examples above, it is essential to set TransactionProvider according to the model that needs to be used, i.e., TransactionProvider.TransactionScope in case of implicit transactions and TransactionProvider.Explicit for explicit transactions. This is something that needs to be done, otherwise the default TransactionProvider.OpenAccess ORM will be used, which does not enlist System.Transactions. |
System.Transactions work in the same way as normal transactions, i.e. all the functionality of a transaction applies to it too. However, there are some inherent restrictions on the usage of System.Transactions with various backends and drivers, which have been mentioned below:
| Driver Name |
Database Name |
Supported |
| genericADO2 |
SQL Server 2005 |
Yes |
| genericADO2 |
MySQL 5.0 |
No |
| genericADO2 |
SQLExpress |
No |
| genericADO2 |
Oracle 9i and higher |
Yes |
| genericADO2 |
Advantage Database Server 8.1 |
Yes * |
| genericADO2 |
SQL Anywhere Server |
No |
| genericADO2 |
SQL Azure |
Yes |
| genericADO2 |
Microsoft SQL Server CE |
Yes |
| genericADO2 |
Firebird |
Yes *** |
| genericADO2 |
SQL Server 2005 |
No |
| genericADO2 |
SQL Server 2000 |
No |
| genericADO2 |
MSDE and SQLExpress |
No |
| Odp |
Oracle 9i and higher |
Yes ** |
| genericADO2 |
VistaDB 4.0 |
No |
| * The System.Transaction support in ADS is currently somewhat limited. Please refer to the "Advantage Transaction Processing System Limitations" section of the ADS 8.1 documentation for more information. |
| ** The ODP driver needs the newest version: 2.102.2.20; earlier versions like the one from Oracle Express will not work for System.Transactions usage! |
| *** Firebird does not really have a prepare phase and it does not support durable enlistment at the moment. |
 |
It is possible to trace the events that take place within the transaction using the .NET Logging Framework (refer to Using the System.Diagnostics.Trace framework with OpenAccess ORM for more information). Using this it will be possible to trace exactly when the transaction is converted into a fully distributed transaction etc. |