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

本文关键字:过程中 应用 Sql 事务 存储过程 存储 是否 代码 我们 | 更新日期: 2023-09-27 18:21:53

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

如果我只在 C# 代码中应用事务,这是一种很好的做法吗?

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

谢谢

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

如果进程只在单个SqlCommand中调用单个存储过程,则只需处理存储过程中的事务,无需从 C# 代码对其进行管理。只需在 C# 代码中对其进行管理,即可跨多个SqlCommand执行维护事务。

仅供参考,仅当满足以下两个条件时,才需要在两层中管理事务:

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

在上述方案之外,管理两层中的事务毫无意义,因为只有一个事务。如果在 C# 代码中启动事务,则调用 BEGIN TRAN 时存储过程中发生的所有情况都是递增@@TRANCOUNT。事务不会真正提交,直到@@TRANCOUNT通过发出与@@TRANCOUNT中所示相同的COMMIT数(在本例中,在存储过程中发出COMMIT并在 C# 代码中再次发出,此时 SQL Server 实际上执行真正的"提交"(,事务才会真正提交。但是,单个ROLLBACK会使@@TRANCOUNT恢复为0,无论它处于什么数字。如果在存储过程中发生这种情况,则无法在 C# 代码中发出COMMITROLLBACK,因为事务不再存在,因此需要先测试活动事务。

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

例如:

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;