C
Charles Rumbold
I have the following code:
SqlConnection cn = new SqlConnection(stdConnectStr )
cn.Open();
SqlTransaction tx = cn.BeginTransaction();
try
{
db.Update( obj );
tx.Commit();
}
catch( Exception ex )
{
tx.Rollback();
throw ex;
}
finally
{
cn.Close();
}
db.Update creates a SqlCommand that executes a stored procedure using
parameters from obj.
The procedure updates table A and updates table B (in order). A & B
both have history triggers on update that insert a row into A_HIST and
B_HIST. This procedure is written as:
UPDATE [A] SET ...
IF @@ERROR <> 0 RAISERROR( 'Failed A', 16, 1 )
UPDATE SET ...
IF @@ERROR <> 0 RAISERROR( 'Failed B', 16, 1 )
None of the procedures or history triggers have any transaction
commands (no commits or rollbacks).
Question 1:
Originally I had the code without the SqlTransaction or tests on
@@ERROR but I found that if the update to B failed, the update to A
remained. I had assumed that everything within one connection and one
procedure was one transaction and didn't need explicit transaction
mangement. Is this right?
Question 2:
If I provoke an error in the procedure (by using RAISERROR) everything
works fine: the exception is caught, the transaction is rolled back,
the connection is closed and the exception is re-thrown.
However if the error is in the history trigger for B, everything is
not fine (found by making a non null column in B_HIST for a nullable
column in B). The exception is caught, and looking at the exception
it is clearly 'Cannot insert NULL into column X for table B_HIST'.
However when tx.Rollback() executes a further error/exception is
thrown: 'The ROLLBACK TRANSACTION request has no corresponding BEGIN
TRANSACTION.'
Can anyone explain to me what is happening here?
I have lots of DB/transaction experience, but on Oracle. Only started
with SqlServer 3 months ago. This is SqlServer 2000 on WinXP.
Many thanks,
Charles
SqlConnection cn = new SqlConnection(stdConnectStr )
cn.Open();
SqlTransaction tx = cn.BeginTransaction();
try
{
db.Update( obj );
tx.Commit();
}
catch( Exception ex )
{
tx.Rollback();
throw ex;
}
finally
{
cn.Close();
}
db.Update creates a SqlCommand that executes a stored procedure using
parameters from obj.
The procedure updates table A and updates table B (in order). A & B
both have history triggers on update that insert a row into A_HIST and
B_HIST. This procedure is written as:
UPDATE [A] SET ...
IF @@ERROR <> 0 RAISERROR( 'Failed A', 16, 1 )
UPDATE SET ...
IF @@ERROR <> 0 RAISERROR( 'Failed B', 16, 1 )
None of the procedures or history triggers have any transaction
commands (no commits or rollbacks).
Question 1:
Originally I had the code without the SqlTransaction or tests on
@@ERROR but I found that if the update to B failed, the update to A
remained. I had assumed that everything within one connection and one
procedure was one transaction and didn't need explicit transaction
mangement. Is this right?
Question 2:
If I provoke an error in the procedure (by using RAISERROR) everything
works fine: the exception is caught, the transaction is rolled back,
the connection is closed and the exception is re-thrown.
However if the error is in the history trigger for B, everything is
not fine (found by making a non null column in B_HIST for a nullable
column in B). The exception is caught, and looking at the exception
it is clearly 'Cannot insert NULL into column X for table B_HIST'.
However when tx.Rollback() executes a further error/exception is
thrown: 'The ROLLBACK TRANSACTION request has no corresponding BEGIN
TRANSACTION.'
Can anyone explain to me what is happening here?
I have lots of DB/transaction experience, but on Oracle. Only started
with SqlServer 3 months ago. This is SqlServer 2000 on WinXP.
Many thanks,
Charles