C# 中SqlTransaction--启动事务 先删除从表,再删除主表

事务的基本原理介绍

msdn中的解释:
https://docs.microsoft.com/zh-cn/dotnet/api/system.data.sqlclient.sqltransaction?view=netframework-4.8
事务是将一系列操作作为一个单元执行,要么成功,要么失败,回滚到最初状态。只要有一个参与者无法做出此保证,整个事务就会失败。事务范围内的所有数据更改将回滚到特定设置点。 事务将多个操作紧密联系到一起,这样就能保证有联系的两种操作的一致性、以及数据的完整性
此外,当提交事务的时候,所有参与者都必须保证对数据的任何更改是永久的。
在这里插入图片描述
启动一个事务的步骤:
(1)利用SqlConnection开启一个事务
(2)利用SqlCommand执行事务,将事务对象和连接都分配给命令对象
(3)执行过程
(4)提交事务
(5)异常捕捉,若出现异常,则从挂起状态滚回事务trans.Rollback();

using (SqlConnection conn =new SqlConnection(SqlHelper.connString))
{
    //事务启动是通过conn来开启
    conn.Open();
    SqlTransaction trans = conn.BeginTransaction();//开启一个事务
    SqlCommand cmd = new SqlCommand(); //利用SqlCommand执行事务
    //为挂起的本地事务将事务对象和连接都分配给命令对象
    cmd.Connection = conn;
    cmd.Transaction = trans;
    try
    {                         
        foreach (int id in listIds)
        {
           //执行过程 
            cmd.CommandText = "update StudentInfo set IsDeleted=1 where StuId=@stuId";
            SqlParameter para = new SqlParameter("@StuId",id);
            cmd.Parameters.Clear();
            cmd.Parameters.Add(para);
            cmd.ExecuteNonQuery()
        }
        trans.Commit();//提交事务,代表所有的事务已经提交到数据库
        Console.WriteLine("Both records are written to database.");
    }
    catch (SqlException ex)
    {
        trans.Rollback();//catch特定用法,从挂起状态滚回事务
        MessageBox.Show(ex.Message, "异常信息捕捉", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
    }
}

项目实例:

拿一个项目中 的例子来说,数据库中有两个表,学生表和班级表,两个表是通过班级号ClassId联系起来的,那么在录入信息的时候,应该先录入班级表中的ClassId再录入学生表的信息;同理,在删除班级信息的时候,先删除从表(和班级有关的学生信息),再删除主表(班级表中的班级信息)

先删除从表(学生表中的班级),再删主表(班级表)

在这里插入图片描述
在这里插入图片描述
实现过程:
把执行事务封装成了一个方法,因为,一条语句,只能执行一次,比如现在想先删除学生表中和班级相关学生信息,再删除班级表中的班级信息。
一般是用两条语句,但是这里我们封装成一个方法,执行多条sql语句的时候,只需要传参数进去,调用一次方法:
1.首先,获取datagridview中的classId,写sql语句并添加参数

int ClassId = int.Parse(dr["classId"].ToString());
//删除该班级对应的学生信息
string sqlDelStudent = "update StudentInfo set IsDeleted=1 where ClassId=@classId";
//删除班级信息
string sqlDelClass = "update ClassInfo set IsDeleted=1 where ClassId=@classId";
SqlParameter[] para = {new SqlParameter ("@ClassId", ClassId) };

2.然后我们定义一个类,负责参数传递

public class CommandInfo
{
   public string CommandText;//sql 或者存储过程名
   public DbParameter[] parameters;//参数列表
   public bool IsProc;//是否存储过程
   public CommandInfo(string comText, bool isProc, DbParameter[] para)
     {
        this.CommandText = comText;//sql语句
        this.IsProc = isProc;//是否存储过程
        this.parameters = para;//参数列表
     }
}

3.然后分别把学生表和班级表中的信息存储在一个泛型List中

List<CommandInfo> listComs = new List<CommandInfo>();
CommandInfo comStudent = new CommandInfo()
{
    CommandText = sqlDelStudent,                         
    parameters = para
};
listComs.Add(comStudent);//添加学生表的sql语句和参数
CommandInfo comClass = new CommandInfo()
{
    CommandText = sqlDelClass,                       
    parameters = para
};
listComs.Add(comClass);//添加班级表的sql语句和参数

4.都添加成功之后只需要调用一次执行事务,方法返回一个bool值,成功则为true否则提示异常

bool bl = SqlHelper.ExcuteTrans(listComs);

5.封装的方法如下,只是把图中执行过程替换
在这里插入图片描述
6.替换为以下:

 int count = 0;
 for (int i = 0; i < comList.Count;i++)//遍历list中所有的变量
 {
     cmd.CommandText = comList[i].CommandText;//获取sql语句   或者存储过程
     if(comList[i].IsProc)//若是存储过程
     {
         cmd.CommandType = CommandType.StoredProcedure;//获取存储过程的名称
     }
     else
     {
         cmd.CommandType = CommandType.Text;//获取sql语句文本
     }
     if(comList[i].parameters.Length>0)//若泛型中的参数列表长度不为0
     {
         cmd.Parameters.Clear();//每次循环都先清空
         cmd.Parameters.AddRange(comList[i].parameters);//再添加
     }
     count += cmd.ExecuteNonQuery();//执行事务过程,并返回受影响 的行数
     cmd.Parameters.Clear();
 }

至此,完成了所需功能,演示如下:
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

积跬步、至千里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值