Thanks a million for that Mike, now I understand most of it. But I still
don't understand why the TransactionContext class must implement the
IDisposable interface...
As a normal user of transactions and connections, I never need to call
connection.dispose() manually neither transaction.dipose()
Then why in this case we need to do that? I had a look at the IDisposable
interface in the MSDN doc but they just say: Defines a method to release
allocated unmanaged resources.
But as far as i know Transactions and connection are managed resource as
they are part of the framework.
Also when does the framework call the Dispose() method?
Sorry for having so many questions !
Thanks in advance,
Francois.
michaeltours said:
It's not fully functional yet but here's something to get you going:
Create a public enum called TransactionMode in your DataTier with 2
Values: Non Transactional / Transactional (call them what you like)
Create a Class called TransactionContext (Implement Idisposable)
public class TransactionContext : IDisposable
{
private SQLConnection _conn;
private SQLTransaction _tran;
private eTransactionMode _transactionMode;
private string_Database;
}
The class Constructor should take a Parameter of TransactionMode (best to
set the mode during construction. Can also setup a Default Database at this
point as most transactions persist over 1 Database. I created an overloaded
constructor so that Database was not required but possible at
construction. )
//Constructor
public TransactionContext(eTransactionMode transactionMode, string database)
{
_transactionmode = transactionmode;
_database = database;
}
The class should encapsulate a SQL connection and a SQL Transaction, and
be able to return references to both. (However in my class they can only be
created internally. There is no property SET for either of these members.)
The Interface should be able to Connect(and begin transaction if the mode
is required). It should understand that if a connection / transaction exists
it does not need to start new ones, it can just use the existing ones.
You should also have COMMIT Method and a ROLLBACK Method. Both are straight forward.
The DISPOSE method (required since you're implementing IDisposable) just
needs to check if either the Connection is not NUll or the Transaction is
not null and call the dispose method on each.
public dispose()
{
if(_conn!=null)
_conn.dispose();
if(_trans!=null)
_trans.dispose();
}
Following the example I gave you earlier, the Business logic is really
easy. You just create a Transaction context object (NOTE: that if you dont
contain it within a "using" statement you MUST call the dispose method
manually as this will release the connection and transaction objects
internally. If you don't then those unmanged resources might stay open very
long !!!
Then, all you gotta do is pass the context to your Data Layer classes (I
do it during construction so that for each Datalayer class it only need to
be passed once.) As each Data layer class inherits your Base Class, you can
just pass that transactioncContext to the base class at construction.
Your base class should have no need for a SQL connection or a SQL
Transaction now as these are inside your Context (Transaction Conext should
be a private member inside your DAL). If you are making a Non transactional
call and you did not need the Transaction context and did not pass it in the
your DAL can just create a New one for the call, anddispose of it directly
after. If you specify a non transaction mode then only a connection should
be created and not a transaction object too.
Inside your DAL you'll most likely have a method to execute a stored
procedure. Inside that method you can simple pass the SQL Command object the
connection from the transactionConext and do the same for the transaction.
Then, just call Commit or Rollback in your business logic.
Thats about it .... I was really bored at work so that's why I typed all
this out .... It's better for you to figure out yourself how this all fits
together !!!!! hope this helps...