- Transaction Overview
- Programmatic Transactions
- Automatic Transactions
- Transactions with Services Without Components
- Transactions Support with ASP.NET
- Transaction Isolation
- Monitoring the DTC
- Transactions with .NET 2.0
- Summary
Transactions with Services Without Components
Starting with Windows Server 2003 and Windows XP SP2, it is possible to create contexts with transactions without defining transactional attributes with serviced component classes. You can create transactional contexts with the ServiceConfig, the ServiceDomain, and the Activity classes. This is not only useful without serviced components, but also with serviced components. With serviced components, this feature makes it possible that one method of a class uses a transaction, whereas another does not use it. For example, with the class CourseData, it would not be necessary to create a transaction with the method GetCourses, where data from the database is read-only, but with the method AddCourse, a transaction is necessary.
The code in Listing 7-10 demonstrates using transactions without serviced components. After reading the connection string from the application configuration file and creating a new object of type CourseData (CourseData is a normal class that does not derive from ServicedComponent), a new ServiceConfig object is created. With the ServiceConfig object, the context can be configured, and the transactional attributes can be set with the Transaction property of this class. The values that can be set with the Transaction property have already been shown: a value from the enumeration TransactionOption. Here TransactionOption.Required is used as the value for the Transaction property. The context is created as soon as we call ServiceDomain.Enter, passing the context configuration information. The next method, data.AddCourse, is running inside the context, and the database connection that is used inside this method is enlisted with the DTC. The transaction is committed when the context is left with ServiceDomain.Leave, which returns the status of the transaction as a value of the enumeration TransactionStatus.
Listing 7-10 Transactions with Services Without Components
using System; using System.EnterpriseServices; using System.Configuration; using Samples.Courses.Data; using Samples.Courses.Entities; class TransactionsWithoutComponents { [STAThread] static void Main() { Course c = new Course(); c.Number = "MS-2524"; c.Title = "ASP.NET Web Services"; c.Active = true; string connectionString = ConfigurationSettings.AppSettings["Database"]; CourseData data = new CourseData(connectionString); // create a transactional context ServiceConfig context = new ServiceConfig(); context.Transaction = TransactionOption.Required; // enter the transactional context ServiceDomain.Enter(context); data.AddCourse(c); // leave the transactional context TransactionStatus status = ServiceDomain.Leave(); Console.WriteLine("Transaction ended with {0}", status); } }
The result of the transaction is returned from the ServiceDomain.Leave method. The possible values are listed in Table 7-4.
Table 7-4 TransactionStatus Enumeration
TransactionStatus |
Description |
Aborted |
The transaction is aborted. Either the database returned an error, or the method generated an exception, so the transaction is aborted. |
Aborting |
The transaction is in the process of being aborted. |
Committed |
The transaction committed successfully. Every member who was participating in the transaction voted the transaction by setting the consistent bit. |
LocallyOk |
The transaction is neither committed nor aborted. This status can be returned, if the context that is left is running inside another transactional context. |
NoTransaction |
The context did not have a context, so NoTransaction is returned. |
Some examples of when it is helpful to use transactions without serviced components are as follows:
Standalone applications.
With ASP.NET Web services that use serviced components, a root transactional context can be created without serviced component configuration.
Services without components can also be useful within serviced components: for example, if the serviced component class has one method that requires a transaction, and another method that doesn’t require one.