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

Abh*_*ava 5 c# sql sql-server stored-procedures

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

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

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

谢谢

Sol*_*zky 6

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

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

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

在上述场景之外,管理两个层中的事务是没有意义的,因为只有一个事务.如果事务是在C#代码中启动的,那么在BEGIN TRAN调用时存储过程中发生的所有事情@@TRANCOUNT都会递增.并且事务没有真正提交,直到@@TRANCOUNT通过发出相同数量的COMMITs 返回到0 @@TRANCOUNT(在这种情况下,COMMIT在存储过程中再次发出一个C#代码,此时SQL Server实际上执行了真正的"承诺").然而,单一ROLLBACK带来@@TRANCOUNT回到0不管它是在什么号码.如果在存储过程中发生这种情况,则无法在事务不再存在时发出COMMITROLLBACK在C#代码中发出,因此您需要首先测试活动事务.

假设您至少使用SQL Server 2005,如果不是更新,请确保使用T-SQL TRY / CATCH语法来管理COMMIT / ROLLBACK存储过程. 即使您只是在C#代码中管理事务,也需要TRY/CATCH语法来正确捕获错误并退出proc(s).

例如:

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;
Run Code Online (Sandbox Code Playgroud)