Introduction
Ever had to return an object to its original state after a user has clicked the Cancel button? I am sure that most of us have, and we have had to write a whole series of special methods to do this, methods that are only valid for that object, and methods that fail when later on we add more properties to the object and forget to modify the 'Transaction' routines.
With the Transaction code that this article covers, simple yet powerful transactions can be easily added to existing and new projects.
Background
On a boring Saturday, I decided to see what VB.NET had to offer that might allow me to dynamically do object transactions. After some searching through MSDN, I came across the System.Reflection
namespace, which offers access to an object's methods, properties, fields, etc. Based on the functions in this namespace, I was able to build the basics of the Transaction Application.
Then I decided that I wanted to be able to control what members of a class would enter into a transaction, and thus I came across the functionality provided by the Attributes
class. This class allows you to create custom values that can be associated with, and read from classes, variables, properties, etc..
And finally, since I found that, when making a 'copy' of an object in a transaction, all that was copied was a reference, and since many classes use collections, I created a weakly typed Collection object that could work in transactions.
Apart from the source code, a demo application DemoTrans is provided that demonstrates some of the basic functionality provided by the application.
Using the code
The Transaction application provides two transactional classes (DeepTrans
and ShallowTrans
) and an interface to make your classes fully transactional (TransBase
), an Attributes class to aid in the definition of transactionality (TransactionalAttribute
), and a weakly typed collection class that works in Transactions (TransactionCollection
).
Each of the provided classes include comments that try and describe how they work and how they can be used. What follows is a brief overview of these classes.
DeepTrans
Copies all the public and private variables of the passed object.
ShallowTrans
Copies all the public Read/Write properties of the passed object.
TransBase
An interface that when implemented allows for the object to be fully transactional, that is a copy will be made instead of a reference. Used for objects that belong to parent objects in a transaction.
To begin to use the Transaction Application with an existing object, we can simply use the following code:
Private Sub DoTransaction()
Dim oTrans as New Transaction.DeepTrans
oTrans.BeginTrans(MyObject, New MyClass)
If bEditCanceled = True Then
oTrans.Rollback()
Else
oTrans.Commit()
End If
End Sub
Now if any of the variables of the object were themselves objects and changes were made to them, these changes were not rolled back. To be able to do this, these objects must implement the TransBase
interface. How this interface needs to be implemented is described in the Interface class definition.
The code for running a Transaction over a class that implements the TransBas
interface is even simpler:
Private Sub DoTransaction()
MyObject.BeginTrans
If bEditCanceled = True Then
MyObject.RollbackTrans()
Else
MyObject.Commit()
End If
End Sub
We can control whether a class, a property, or a variable will be covered by a transaction, by setting a custom attribute using the Attribute class provided, TransactionalAttribute
.
<Transaction.Transactional(True)>Public Class MyObject
<Transaction.Transactional(False)>Public Class MyObject
<Transaction.Transactional(True)>Private MyVar As Integer
<Transaction.Transactional(False)>Private MyVar As Integer
<Transaction.Transactional(True)>Public Property MyProp() As Integer
<Transaction.Transactional(False)>Public Property MyProp() As Integer
Additionally, classes that implement the TransBase
interface expose methods that allow you to programmatically change the transactionality of the class at run time:
SetTransactionality
Takes a boolean parameter that changes the transactionality of the class.
ResetTransactional
Resets the class to use its attribute.
Transactional
Returns the current transactionality of the class.
As I mentioned above, one issue I came across was the fact that even at this level, when treating objects, what was copied was a reference. Since many classes that need this type of functionality use collections or collection based members, this was a problem. So, using the TransBase
interface and inheriting from System.Collections.CollectionBase
, I created a weakly typed collection object, TransactionCollection
, that uses string and object arrays to maintain its data, and thus can enter into transactions.
While this collection is weakly typed, it can easily be inherited to provide strongly typed collection objects. Comments in the code explain what needs to be done with this.
Points of Interest
Writing this code was a blast ... I feel like I have only touched the tip of the iceberg where it comes to the functionality that VB.NET exposes. Attributes and the System.Reflection
namespace open up a whole new realm of possibilities in VB.
History
This first version (18 Oct 2004) has been more or less tested, but has yet to used in a real-life application ....
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.