O
Ola Strandberg
I am building a multi-tier app (similar to the design of MS PetShop). My
original intention was to use MS DTC and declarative/automatic transactions,
but having run into a million problems and having read some performance
stats, I am at least investigating an alternative path:
The BLL (Business Logic Layer) that is the transaction boundary, but would
contain no transaction code other than [AutoComplete] attributes, etc, now
has some knowledge of transactions. Each DAL (Data Access Layer) method has
a ref IDbTransaction parameter, which they test for null and initialize if
they are.
This results in DAL code similar to:
public void MyMethod(...., ref IDbTransaction trans)
{
OracleConnection conn = null;
if ( trans == null )
{
conn = new OracleConnection(CONN_STRING);
trans = conn.BeginTransaction();
}
else
{
conn = (OracleConnection)trans.Connection;
}
:
OracleCommand cmd = ...
cmd.Connection = conn;
cmd.Transaction = (OracleTransaction)trans;
:
}
and BLL code similar to:
IDbTransaction trans = null;
try
{
DALFactory.Create().MyMethod(..., trans);
DALFactory.Create().MyOtherMethod(..., trans);
}
catch ( Exception e )
{
IDbConnection conn = trans.Connection;
trans.Rollback();
conn.Close();
throw e;
}
IDbConnection conn = trans.Connection;
trans.Commit();
conn.Close();
Not very elegant.... I can swallow the transaction stuff in the BLL code,
but I would really prefer it if I could end each DAL method with a
conn.Close() as I would if I was using EnterpriseServices.
Is there a more elegant solution? What happens if I call conn.Close() with a
running transaction? I suppose I could try it, but I am still interested in
input and suggestions on what to do.
Cheers,
Ola
original intention was to use MS DTC and declarative/automatic transactions,
but having run into a million problems and having read some performance
stats, I am at least investigating an alternative path:
The BLL (Business Logic Layer) that is the transaction boundary, but would
contain no transaction code other than [AutoComplete] attributes, etc, now
has some knowledge of transactions. Each DAL (Data Access Layer) method has
a ref IDbTransaction parameter, which they test for null and initialize if
they are.
This results in DAL code similar to:
public void MyMethod(...., ref IDbTransaction trans)
{
OracleConnection conn = null;
if ( trans == null )
{
conn = new OracleConnection(CONN_STRING);
trans = conn.BeginTransaction();
}
else
{
conn = (OracleConnection)trans.Connection;
}
:
OracleCommand cmd = ...
cmd.Connection = conn;
cmd.Transaction = (OracleTransaction)trans;
:
}
and BLL code similar to:
IDbTransaction trans = null;
try
{
DALFactory.Create().MyMethod(..., trans);
DALFactory.Create().MyOtherMethod(..., trans);
}
catch ( Exception e )
{
IDbConnection conn = trans.Connection;
trans.Rollback();
conn.Close();
throw e;
}
IDbConnection conn = trans.Connection;
trans.Commit();
conn.Close();
Not very elegant.... I can swallow the transaction stuff in the BLL code,
but I would really prefer it if I could end each DAL method with a
conn.Close() as I would if I was using EnterpriseServices.
Is there a more elegant solution? What happens if I call conn.Close() with a
running transaction? I suppose I could try it, but I am still interested in
input and suggestions on what to do.
Cheers,
Ola