SqlTransaction 数据库事务

事务(Transaction):一组SQL操作原子执行,要么全部成功提交(Commit),要么全部失败回滚(Rollback),满足ACID特性。
在.NET Framework/.NET中使用 SqlTransaction(SQL Server专属)实现。

流程要点:

  1. 打开数据库连接 conn.Open()
  2. 通过连接开启事务 conn.BeginTransaction()
  3. 将事务对象绑定到 SqlCommand.Transaction
  4. 批量执行多条SQL
  5. 无异常:tx.Commit();捕获异常:tx.Rollback()

例子

原图代码缺失catch回滚逻辑,完整可运行版本

public static int ExecuteSqlTran(List<string> SQLStringList)
{
    using (SqlConnection conn = new SqlConnection(connectionString))
    {
        conn.Open();
        SqlCommand cmd = new SqlCommand();
        cmd.Connection = conn;
        SqlTransaction tx = conn.BeginTransaction();
        cmd.Transaction = tx;
        try
        {
            int count = 0;
            for (int n = 0; n < SQLStringList.Count; n++)
            {
                string strsql = SQLStringList[n];
                if (strsql.Trim().Length > 1)
                {
                    cmd.CommandText = strsql;
                    count += cmd.ExecuteNonQuery();
                }
            }
            tx.Commit(); // 全部执行成功,提交事务
            return count;
        }
        catch (Exception ex)
        {
            tx.Rollback(); // 任意一条出错,整体回滚
            throw ex; // 向外抛出异常,上层感知失败
        }
    }
}Code language: C# (cs)

这个版本直接拼接SQL字符串,存在SQL注入风险,适合理解事务原理;正式项目优先使用参数化查询

带参数化的事务示例

循环插入数据,使用SqlParameter防止注入,关键点:

  1. 循环末尾调用 sqlCom.Parameters.Clear() 清空上一轮参数,避免参数堆积报错
  2. 同一个SqlCommand对象复用,只修改CommandText与参数
SqlCommand sqlCom = new SqlCommand();
sqlCom.Connection = conn;
SqlTransaction st = conn.BeginTransaction();
sqlCom.Transaction = st;
int res = 0;
try
{
    for (int i = 0; i < 10; i++)
    {
        sqlCom.CommandText = "INSERT INTO [dbo].[Article]([Title])VALUES(@Title)";
        SqlParameter param = new SqlParameter("@Title", SqlDbType.NVarChar, 250);
        param.Value = i + "这是新的标题" + DateTime.Now;
        sqlCom.Parameters.Add(param);
        res += sqlCom.ExecuteNonQuery();
        sqlCom.Parameters.Clear(); // 清空参数,下一轮使用
    }
    st.Commit();
}
catch (Exception)
{
    st.Rollback(); // 出现异常,全部撤销
}Code language: C# (cs)

1. 必须遵守的强制规则

  • BeginTransaction() 必须在连接Open之后
  • SqlCommand 必须指定 Transaction 属性,否则会抛出异常
  • Commit() / Rollback() 之后事务自动结束,不能重复调用

其他

  • .NET Core/.NET 5+ 推荐使用 using 自动释放 SqlTransaction
  • 超大量SQL批量场景,可以考虑 SqlBulkCopy,性能优于循环ExecuteNonQuery
  • 如果需要跨数据库事务,SqlTransaction无法支持,需要分布式事务(TransactionScope

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注