【问题标题】:Which one works better? Transaction in SQL Server or in C#?哪一种效果更好? SQL Server 或 C# 中的事务?
【发布时间】:2020-02-25 09:14:18
【问题描述】:

我编写的存储过程具有读取未提交事务隔离级别,但是当连接超时时,SQL 中的 catch 中的回滚不起作用。

当我在.Net的业务层中使用SqlTransaction时,问题就解决了 并且我可以在.Net 中的try... catch 中支持SQL 中发生的任何错误。

这是我做对了吗?

using (SqlConnection conn = new SqlConnection(Data.DataProvider.Instance().ConnectionString))
{
    conn.Open();

    SqlTransaction tran = conn.BeginTransaction(IsolationLevel.ReadUncommitted, "Trans");

    try
    {
        object ores = SqlHelper.ExecuteScalar(.......)
        string res = ores.ToString();

        if (string.IsNullOrEmpty(res))
        {
            tran.Rollback();
            info.TrackingCode = "";
            return 0;
        }
        else if (res == "-4")
        {
            tran.Rollback();
            return -4;
        }
        else if (res == "-1")
        {
            tran.Rollback();
            return -1;
        }
        else
        {
            tran.Commit();
            return 1;
        }
   }
   catch (Exception)
   {
       tran.Rollback();
       info.TrackingCode = "";
       return 0;
   }

【问题讨论】:

  • 我用的是SqlServer
  • 您是否在存储过程的主体中启动事务?
  • 第一次是的,但是当没有发生回滚时,我想在.Net中使用事务
  • 你能提供一些你的 SQL 代码来找出那里可能发生的事情吗?
  • 无论如何,这两种方式都是等价的。但在业务层的情况下,您可以通过多次查询执行来处理事务。

标签: c# sql-server transactions


【解决方案1】:

根据您的要求,可以有两种方式来定义 SqlTransactions

  1. SQL Server 端 SqlTransaction
  2. C#.NET(业务层)SqlTransaction。

(两者不能混用)

在您的情况下,您尝试在业务层定义SqlTransaction。所以最好在业务层也调用Stored-procedure。所以业务层会对SqlTransaction进行整改,不会出现超时错误。

因此,首先将您的Stored-Procedure 代码包含为命令执行(在业务层),然后执行。 根据您所需的条件更改您的代码如下。

                // Command Objects for the transaction
                SqlCommand cmd1 = new SqlCommand("YourStoredProcedureName", cnn);
                cmd1.CommandType = CommandType.StoredProcedure;

                //If you are using parameter for the Stored-procedure
                cmd1.Parameters.Add(new SqlParameter("@Param1", SqlDbType.NVarChar, 50));
                cmd1.Parameters["@Param1"].Value = paramValue1;

                //Execute stored procedure through C# code
                cmd1.ExecuteNonQuery();
                transaction.Commit();

已编辑: Reference link

catch (SqlException sqlEx)
{
    if (sqlEx.Number == -2)
    {
       //handle timeout
    }
    transaction.Rollback();
}

【讨论】:

  • 在这种情况下,您不能在存储过程之外设置事务,但我认为即使在存储过程中设置事务也是不可行的。因此,尝试按照我上面定义的方式转换您的代码,这应该可以工作!
  • @hamidrezaHeydari:请参阅此以在脚本中获得清晰的想法stackoverflow.com/questions/15431285/… >
  • @hamidrezaHeydari:我不这么认为,但你可以使用SqlException 输入catch。请参阅我编辑的答案部分。
【解决方案2】:

两种方式是等价的。但在业务层的情况下,您可以通过多次查询执行来处理事务。
在这里,您应该处理 conn.Open() 可能的异常。此外,请检查 SqlHelper 在其代码中的任何位置使用您创建的连接和事务。

【讨论】:

    【解决方案3】:

    当发生客户端超时事件(例如 .net CommandTimeout)时,客户端会向 SQL Server 发送“ABORT”。 SQL Server 然后简单地放弃查询处理。没有事务回滚,没有锁被释放。我用 .Net 代码中的 Sqltransaction 解决了这个问题,而不是 Sql 和使用 SqlExceptions 管理异常

    【讨论】:

      猜你喜欢
      • 2016-06-27
      • 2010-12-29
      • 2014-12-07
      • 2020-04-26
      • 1970-01-01
      • 1970-01-01
      • 2017-04-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多