我们是否还需要在C#代码和存储过程中应用Sql Transaction?

时间:2014-09-13 05:28:09

标签: c# sql sql-server stored-procedures

我有一个存储过程,它正在更新SQL Server中的多个表。此过程正在使用C#代码。

如果我只在C#代码中应用交易,这是一个好习惯吗?

我是否需要在C#代码和存储过程中应用事务?

由于

1 个答案:

答案 0 :(得分:6)

如果进程只在单个SqlCommand中调用单个存储过程,那么只需处理存储过程内的事务,就不需要从C#代码管理它。您只需要在C#代码中对其进行管理,以便在多个SqlCommand执行中维护事务。

仅供参考,只有满足以下两个条件时才需要在两个层中管理交易:

  • C#代码正在进行需要被视为单个操作的多个SqlCommand调用
  • 存储过程可以/将在此C#代码之外调用,例如通过其他存储过程调用(在这种情况下,存储过程可能没有现有事务)调用。

在上述场景之外,管理两个层中的交易毫无意义,因为只有一个交易。如果事务是在C#代码中启动的,则调用BEGIN TRAN时存储过程中发生的所有事情都会增加@@TRANCOUNT。并且@@TRANCOUNT通过发出COMMIT中显示@@TRANCOUNT的相同数量(在这种情况下,发出COMMITROLLBACK返回到0之前,事务才会真正提交。在存储过程中再次在C#代码中,此时SQL Server实际上执行了真正的" commit")。但是,单个@@TRANCOUNT会将COMMIT带回0,无论它处于什么数字。如果在存储过程中发生这种情况,则无法在C#代码中发出ROLLBACKTRY / CATCH,因为事务不再存在,因此您需要首先测试活动事务。

假设您至少使用SQL Server 2005,如果不是更新,请确保使用T-SQL COMMIT / ROLLBACK语法来管理存储过程中的BEGIN TRY BEGIN TRAN; UPDATE Table1 ... ; UPDATE Table2 ... ; UPDATE Table3 ... ; COMMIT TRAN; END TRY BEGIN CATCH IF (@@TRANCOUNT > 0) BEGIN ROLLBACK TRAN; END; THROW; -- if using SQL Server 2012 or newer, else use RAISERROR END CATCH; 即使您只是在C#代码中管理事务,也需要TRY / CATCH语法来正确捕获错误并退出proc。

例如:

{{1}}