事务的概念:事务是作为单个逻辑工作单位执行的一系列操作,多个操作作为一个整体 向系统提交,要么都执行并且事务是不可分割的工作逻辑单位。
比如举个例子:银行转账的事务,需要俩条更新记录进行转账,如果要是一条出现错误,则整个转账业务需要终止,所以可以把转账当成一个整体。
事务的特性
- 原子性:事务是一个完整的整体,事务各部操作是不可分的要么都执行 要么都不执行
- 一致性:事务完成时候 数据必须保持一致的状态
- 隔离性:多个事务之间彼此隔离、独立、互不影响。
- 永久性:事务完成时候 它对数据库的修改,被永久保存
事务的分类
- 显式事务:通过begin transaction明确指定开启事务 ,最常用的事务类型
- 隐形事务:通过set transaction on 语句 把隐形的事务模式打开,其后面的sql语句将自动开启一个事务,然后提交或者回滚事务之后,下一个sql将开启另外一个事务
- 自动提交的事务:sqlserver默认模式 每一句sql都可以视为一个事务
如何创建事务
- 开始事务:begin transaction
- 提交事务:commit transaction
- 回滚(撤销)事务:rollback transaction
如何在C#中调用事务
测试事务回滚的方法
private void button1_Click(object sender, EventArgs e)
{
//删除前学生总个数
int num1 = (int)GetSingleCount("select count(*) from Students");
this.listBox1.Items.Add("删除前学生总个数:"+ num1); // 展示在listbox下
// 测试删除学生失败进行事务回滚操作
//定义一个列表字符串
List<string> list = new List<string>()
{
"delete from Students where StudentId = 1000005",
"delete from Students where StudentId = 1000024",
"delete from Students where StudentId = 1000006"
};
//执行删除操作 把list里面每一句sql都去执行一下
int result = 0;
try
{
result = UpdateDataBase(list);
}
catch (Exception ex)
{
this.listBox1.Items.Add(ex.Message);
}
if (result > 0)
{
this.listBox1.Items.Add("删除成功");
}
else
{
this.listBox1.Items.Add("删除失败");
}
this.listBox1.Items.Add("删除之后剩余人数为:" + (int)GetSingleCount("select count(*) from Students"));
}
测试事务提交的方法
private void button2_Click(object sender, EventArgs e)
{
//删除前学生总个数
int num1 = (int)GetSingleCount("select count(*) from Students");
this.listBox1.Items.Add("删除前学生总个数:" + num1); // 展示在listbox下
// 测试删除学生失败进行事务回滚操作
//定义一个列表字符串
List<string> list = new List<string>()
{
"delete from Students where StudentId = 1000033",
"delete from Students where StudentId = 1000031",
"delete from Students where StudentId = 1000032"
};
//执行删除操作 把list里面每一句sql都去执行一下
int result = 0;
try
{
result = UpdateDataBase(list);
}
catch (Exception ex)
{
this.listBox1.Items.Add(ex.Message);
}
if (result > 0)
{
this.listBox1.Items.Add("删除成功");
}
else
{
this.listBox1.Items.Add("删除失败");
}
this.listBox1.Items.Add("删除之后剩余人数为:" + (int)GetSingleCount("select count(*) from Students"));
}
封装多个删除语句执行操作
public int UpdateDataBase(List<string> list)
{
SqlConnection conn = new SqlConnection(connString);
// new SqlCommand(sql, conn)
// 没有指定执行sql 没有指定连接,下面必须在写代码把连接对象添加上
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
try
{
conn.Open();
//开启事务
cmd.Transaction = conn.BeginTransaction();
int result = 0;//记录删除时候受影响的行数
//取出每一个sql语句 分别执行
foreach (string sql in list)
{
//设置执行的sql
cmd.CommandText = sql;
result += cmd.ExecuteNonQuery();
// cmd.ExecuteNonQuery() 返回受影响行数如果删除成功了,受影响行数不为0
}
//如果执行错误了 跳转到catch里面 在catch执行回滚
// 没有出错 提交事务
cmd.Transaction.Commit();
return result;
}
catch(Exception ex)
{
if (cmd.Transaction != null)
{
cmd.Transaction.Rollback(); // 执行sql语句有错误的情况 执行回滚操作
}
throw new Exception("执行删除sql事务出错:" + ex.Message);
}
finally
{
// 不管是否执行有误 把事务置为null 清除事务
if(cmd.Transaction!=null)
{
cmd.Transaction = null;
}
conn.Close();
}
}
获取数据库个数的方法