在开始介绍文章主要内容前先简单说一下事务

1.事务介绍

  事务是一种机制、是一种操作序列,它包含了一组数据库操作命令,这组命令要么全部执行,要么全部不执行。因此事务是一个不可分割的工作逻辑单元。在数据库系统上执行并发操作时事务是作为最小的控制单元来使用的。这特别适用于多用户同时操作的数据通信系统。

2.事务使用场景

  需要对数据库同时进行多条更新操作时!例如,电商平台的下单付款,银行转账之类的


  好了,这里就不对事物进行细说了,想了解更多与事务有关的详细知识可以去园子里搜索哈

  执行事务的步骤

  1.连接数据库,连接数据库后会返回一个SqlConnection对象,我这里在数据库连接后将其赋值给了一个全局的SqlConnection对象——_con

  2.用返回的SqlConnection对象用BeginTransaction()方法生产并开始一个事务对象。

  3.执行所有对数据库进行更改操作的Sql语句。

   在对数据库进行更改时需要用到SqlCommand,在用生成SqlCommand对象后必须给其绑定事务(Transaction),不绑定会报错。

     在这里需要注意的是所有SqlCommand对象绑定的SqlConnection必须是同一个SqlConection对象,所有SqlCommand对象绑定的事务对象必须是同一个事务对象。若没绑定相同的SqlConnection对象和SqlTransaction,事务便会如同虚设。

  4.所有Sql语句执行成功后SqlTransaction对象可使用Commit()方法提交事务,失败则用Rollback()回滚事务,将数据库回滚到第一天sql执行前的状态。

  5.关闭数据库连接,释放资源。

  话不多说搬Code,注释代码上都有,如有不明白的地方或是有更好的意见请在下方留言区留下你的评论

事务方法

public static int ModifyDatabaseTran(List<string> SqlStrList, List<SqlParameter[]> SqlParList) {
int result = ;
//打开数据库连接
SqlConnection con = OpenDatabase();
//_con:全局SqlConnection对象
//生成事物对象
SqlTransaction tran = _con.BeginTransaction();
try
{
//遍历并执行SqlStrList集合里面的Sql语句
for (int i = ; i < SqlStrList.Count; i++)
{
//将Sql语句与其对应的SqlParameter[]绑定并生成SqlCommand对象
SqlCommand com = BulidCommand(SqlStrList[i], SqlParList[i]);
//给SqlCommand对象绑定事务,必须绑定同一个事务对象否则跑不出事务效果
com.Transaction = tran;
//返回受影响的行数
result = com.ExecuteNonQuery();
}
//若最后执行的sql是插入语句result的值便=0,这里将其值改为1告诉调用者sql语句执行成功
if (result == ) result = ;
//所有Sql语句执行成功后提交事务
tran.Commit(); }
catch (Exception)
{
//SqlStrList集合里面有一条Sql语句执行失败便执行事务回滚操作,回滚后报错Sql语句之前执行的Sql语句都将无效
//同时数据库恢复SqlStrList集合里面的Sql语句执行前的状态
          result=0;
tran.Rollback(); }
finally
{
//关闭数据库连接,释放资源
if (_con != null && _con.State != ConnectionState.Closed) {
_con.Close();
con.Dispose();
}
tran.Dispose(); }
//返回结果 0:失败,1:成功
return result;
}

打开数据库连接的方法

//数据库连接字符串
private const string conStr = "server=.;database=Food;uid=sa;pwd=123456"; private static SqlConnection _con; /// <summary>
/// 打开数据库连接
/// </summary>
/// <returns></returns>
private static SqlConnection OpenDatabase() {
if (_con == null || _con.State == ConnectionState.Closed)
{
_con = new SqlConnection(conStr);
_con.Open();
}
return _con;
}

生产SqlCommand对象方法

/// <summary>
/// 参数化查询绑定参数
/// </summary>
/// <param name="sqlStr"></param>
/// <param name="SqlPar"></param>
/// <returns></returns>
private static SqlCommand BulidCommand(string sqlStr,SqlParameter[] SqlPar) {
SqlConnection con = OpenDatabase();
SqlCommand com = new SqlCommand(sqlStr, con);
com.Parameters.AddRange(SqlPar);
return com;
}

实例

下面例子本来是想用winform写个注册,结界觉着拖控件太麻烦了,索性就直接在代码里面写sql了

页面(输入框可以自动忽略,这里只用到了按钮的点击事件)

执行操作前的member表状态

注册按钮点击事件代码(页面控件是从登陆页面复制过来的注册按钮的Name属性没有更改所以事件名称是LoginBtn_Click而不是RegisterBtn_Click)

private void LoginBtn_Click(object sender, EventArgs e)
{
List<string> sqlStr = new List<string>
{
{ @"insert member values(@MemberAccount,@Password)"},
{ @"insert member values(@MemberAccount,@Password)"}
};
List<SqlParameter[]> sqlPar = new List<SqlParameter[]>
{
new SqlParameter[] { new SqlParameter("@MemberAccount","lei1"), new SqlParameter("@Password", "") },
new SqlParameter[] { new SqlParameter("@MemberAccount","lei2"), new SqlParameter("@Password", "") }
}; int result=DBHlep.ModifyDatabaseTran(sqlStr,sqlPar);
if (result > )
{
MessageBox.Show("成功!");
}
else {
MessageBox.Show("失败!");
}
}

点击注册按钮后我们再来看看member表状态

上面的是Sql语句不报错的执行结果,接下来,我们将第二条sql语句的表名从menber改为menber1,看看member表的数据会发生什么变化

PS:我的数据库里面没有表member1所以第二条sql必定会执行失败,第二条sql失败后我们看看表member是否新增了一条数据(第一条sql是正确的,只修改了第二条sql的表名),新增了一条数据则事务执行失败,反之事务执行成功

private void LoginBtn_Click(object sender, EventArgs e)
{
List<string> sqlStr = new List<string>
{
{ @"insert member values(@MemberAccount,@Password)"},
//将第二条sql的表名修改为member1
{ @"insert member1 values(@MemberAccount,@Password)"}
};
List<SqlParameter[]> sqlPar = new List<SqlParameter[]>
{
new SqlParameter[] { new SqlParameter("@MemberAccount","lei1"), new SqlParameter("@Password", "") },
new SqlParameter[] { new SqlParameter("@MemberAccount","lei2"), new SqlParameter("@Password", "") }
}; int result=DBHlep.ModifyDatabaseTran(sqlStr,sqlPar);
if (result > )
{
MessageBox.Show("成功!");
}
else {
MessageBox.Show("失败!");
}
}

点击注册按钮后看表member的数据是否发生了变化

member表数据未发生变化,事务执行成功!

好了,这篇博客到这里就结束了,如有不明白之处或是有更好的意见请在下方留言区留下你的评论

AOD.NET实现数据库事物Transaction的更多相关文章

  1. 数据库事物四大特性-ACID

    事务的:原子性.一致性.分离性.持久性 事物(transaction)是由一些列操作序列构成的执行单元,这些单元要么都做,要么不做,是一个不可分割的工作单元. 数据库事物的四个基本性质(ACID) 1 ...

  2. SpringBoot事物Transaction实战讲解教程

    前言 本篇文章主要介绍的是SpringBoot的事物Transaction使用的教程. SpringBoot Transaction 说明:如果想直接获取工程那么可以直接跳到底部,通过链接下载工程代码 ...

  3. 数据库事物用法 SET XACT_ABORT ON

    数据库事物的用法和作用就不再重复,写一下在实战当中遇到的问题,代码如下: begin tran --开始执行事务     --语句一 update  set acount = acount-100 w ...

  4. Spring中的数据库事物管理

    Spring中的数据库事物管理 只要给方法加一个@Transactional注解就可以了 例如:

  5. 数据库事物 jdbc事物 spring事物 隔离级别:脏幻不可重复读

    1.数据库事物: 事物的概念 a给b打100块钱的例子 2.jdbc事物: 通过下面代码实现 private Connection conn = null; private PreparedState ...

  6. Spring+Mybatis+SpringMVC+Atomikos多数据源共存+不同数据库事物一致性处理

    网上找了一大堆的例子,没一个跑通的,都是copy转发,哎,整理得好辛苦..做个笔记,方便正遇到此问题的猿们能够得到帮助....废话不多说,贴代码..... 项目结构说明: 1.dao层的admin.w ...

  7. Spring 事物Transaction

    日常开发中Spring 为我们提供了两种事物的定义方式 XML 配置 方式 :这种方式配置起来比较麻烦,但后期比较好进行维护 注解方式:配置起来比较方便,也是日常开发常用的: 我们这里进行第二种注解的 ...

  8. 数据库事务(Transaction)

    事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit). 事务四大特性(ACID): 原子性(Atomicity):个事务是一个不可分割的工作单位,事务中包括的 ...

  9. SQL Server 2008 中收缩数据库(DUMP,TRANSACTION,TRAN,无效,语法错误)

    从SQL SERVER 2008 开始,我们已经不能再用以前 DUMP TRAN 数据库名 WITH NO_LOG 的这种方式来收缩数据库,但是,可以用另外一种替代的方法,SQL语句如下: ALTER ...

随机推荐

  1. linux用户管理章节笔记

    1 更改有效用户组 :newgrp zeng 把当前用户的有效用户组更改为zeng.事后可以使用groups命令查看. 2 在使用useradd命令增加用户时,在/etc/passwd的值一般会参考 ...

  2. 告诉你一些DBA求职面试技巧

    告诉你一些DBA求职面试技巧 要自信!永远不要低估你的能力.如果你不了解什么问题的答案,承认它.重点放在你找出答案的能力和你学习的意愿. 不要自大!是的,你可能过于自信而被认为是骄傲的.轻率的,甚至是 ...

  3. 联邦学习(Federated Learning)

    联邦学习简介        联邦学习(Federated Learning)是一种新兴的人工智能基础技术,在 2016 年由谷歌最先提出,原本用于解决安卓手机终端用户在本地更新模型的问题,其设计目标是 ...

  4. Node.js连接数据库取值,简单接口的实现

    第一步:先安装Node.js,这里不做介绍 第二步:新建一个文件夹,打开cmd,进入该文件夹 执行npm init命令生成page.json文件 第三步:安装如下模块,打开cmd,进入第二步的文件夹, ...

  5. luoguP4770 [NOI2018]你的名字

    题意 不妨先考虑\(l=1,r=|S|\)的情况: 这时我们要求的其实是\(S,T\)的本质不同的公共子串数量. 首先对\(S\)建一个后缀自动机,同时对于每个\(T\),我们也建一个自动机. 根据后 ...

  6. Python str & repr

    Python str & repr repr 更多是用来配合 eval 的 (<- 点击查看),str 更多是用来转换成字符串格式的 str() & repr() str() 和 ...

  7. K-消亡的质数-(简单数学)

    https://ac.nowcoder.com/acm/contest/3346/K 题意:判断一个素数p是不是某两个数的立方差. 刚看到这道题一时半会都没有什么思路,看了题解恍然大悟,太久没碰数学或 ...

  8. Note | Ubuntu18.04安装与配置

    目标: 在服务器上配置最新的Ubuntu稳定版本18.04 LTS.18.04比16.04好看很多,非常建议. 有3块硬盘:2块4TB机械硬盘,1块2TB固态硬盘.计划将固态硬盘作为主硬盘,其余两块机 ...

  9. JVM调优YoungGC

    先上代码: 主函数:   public class GCDemo {       public static void main(String[] args) throws InterruptedEx ...

  10. 【解决错误】Non-reversible reg-exp portion: '(?i'

    在将Django升级到2.1后,运行 Django 自带后台后,或 使用 redirect 方法,就一直报错:Non-reversible reg-exp portion: '(?i'. 错误一 Dj ...