Telerik OpenAccess Classic

Telerik OpenAccess ORM Send comments on this topic.
System.Transactions
Programmer's Guide > OpenAccess ORM Classic (Old API) > Programming With OpenAccess > Transactions > System.Transactions

Glossary Item Box

This documentation article is a legacy resource describing the functionality of the deprecated OpenAccess Classic only. The contemporary documentation of Telerik OpenAccess ORM is available here.

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()
  ' Transaction to modify object
  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()
  ' Transaction to modify object
  Using txn As New CommittableTransaction()
   ' Enlisting the connection in the transaction scope
   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.