.NET事务应用原则

1.在同一个数据库内进行CRUD时,应使用同一个DbConnection对象,且显式指定DbConnection均为同一个DbTransaction,示例代码如下:

//在同一个DB中操作一个表时,可以不用显式指定事务,因为单条SQL命令就是一个最小的事务单元
using (DbConnection conn = new SqlConnection("数据库连接字符串"))
{
var cmd = conn.CreateCommand();
cmd.CommandText = "delete users";
cmd.ExecuteNonQuery();
} //在同一个DB中操作多个表或执行不同的SQL命令时,需要显式指定事务,且需确保每个Command均与同一个DbTransaction关联
using (DbConnection conn = new SqlConnection("数据库连接字符串"))
{
DbTransaction tran = conn.BeginTransaction();
try
{
var cmd = conn.CreateCommand();
cmd.Transaction = tran;
cmd.CommandText = "delete users";
cmd.ExecuteNonQuery(); var cmd2 = conn.CreateCommand();
cmd2.Transaction = tran;
cmd2.CommandText = "delete roles";
cmd2.ExecuteNonQuery(); tran.Commit();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
tran.Rollback();
}
}

2.在同一个服务器上的不同数据库之间进行CRUD时,应使用同一个DbConnection对象,且显式指定DbConnection均为同一个DbTransaction,同时SQL命令语句中的包含的对象(表、视图、存储过程、函数等)应显式指定数据库名称,格式如:databasename.owner.tablename,如:Db1.dbo.Users;Db2.dbo.Users;(前提条件:多个数据库的用户名及密码相同的情况下,否则就只能使用分布式事务),示例代码如下:

//在同一个Server不同的DB中操作多个表或执行不同的SQL命令时,需要显式指定事务,且需确保每个Command均与同一个DbTransaction关联,CommandText还应显式添加数据库名称
using (DbConnection conn = new SqlConnection("数据库连接字符串"))
{
DbTransaction tran = conn.BeginTransaction();
try
{
var cmd = conn.CreateCommand();
cmd.Transaction = tran;
cmd.CommandText = "delete db1.dbo.users";
cmd.ExecuteNonQuery(); var cmd2 = conn.CreateCommand();
cmd2.Transaction = tran;
cmd2.CommandText = "delete db2.dbo.roles";
cmd2.ExecuteNonQuery(); tran.Commit();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
tran.Rollback();
}
}

3.在不同的DB服务器上进行CRUD时,应使用分布式事务,可以采取隐式或显式开启分布式事务,示例代码如下:

//采用隐式开启分布式事务
using (TransactionScope tranScope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
using (DbConnection conn = new SqlConnection("数据库连接字符串"))
{
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandText = "delete users";
cmd.ExecuteNonQuery();
} using (DbConnection conn2 = new SqlConnection("数据库连接字符串2"))
{
conn2.Open();
var cmd2 = conn2.CreateCommand();
cmd2.CommandText = "delete users";
cmd2.ExecuteNonQuery();
}
tranScope.Complete();
} //采用显式开启分布式事务
using (CommittableTransaction committableTransaction = new CommittableTransaction())
{
try
{
using (DbConnection conn = new SqlConnection("数据库连接字符串"))
{
conn.Open();
conn.EnlistTransaction(committableTransaction); //将连接登记到可提交事务
var cmd = conn.CreateCommand();
cmd.CommandText = "delete users";
cmd.ExecuteNonQuery();
} using (DbConnection conn2 = new SqlConnection("数据库连接字符串2"))
{
conn2.Open();
conn2.EnlistTransaction(committableTransaction); //将连接登记到可提交事务
var cmd2 = conn2.CreateCommand();
cmd2.CommandText = "delete users";
cmd2.ExecuteNonQuery();
} committableTransaction.Commit();
}
catch (Exception ex)
{
committableTransaction.Rollback(ex);
}
} //采用显式开启分布式事务,模拟TransactionScope用法的过程
{
Transaction originalTransaction = Transaction.Current; //记录当前的环境事务,用于后面的恢复
CommittableTransaction committableTransaction = null;
DependentTransaction dependentTransaction = null;
committableTransaction = new CommittableTransaction();
Transaction.Current = committableTransaction;//将定义的可提交事务作为当前的环境事务 try
{ using (DbConnection conn = new SqlConnection("数据库连接字符串"))
{
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandText = "delete users";
cmd.ExecuteNonQuery();
} dependentTransaction = Transaction.Current.DependentClone(DependentCloneOption.RollbackIfNotComplete); //复制当前的环境事务从而产生新的依赖事务,且指定必需等到该事务完成
Transaction.Current = dependentTransaction;//将复制到的新的依赖事务 using (DbConnection conn2 = new SqlConnection("数据库连接字符串2"))
{
conn2.Open();
var cmd2 = conn2.CreateCommand();
cmd2.CommandText = "delete users";
cmd2.ExecuteNonQuery();
} dependentTransaction.Complete();
committableTransaction.Commit();
}
catch (Exception ex)
{
Transaction.Current.Rollback(ex);
}
finally //不论成功与否,最终都将恢复成原来的环境事务
{
Transaction transaction = Transaction.Current;
Transaction.Current = originalTransaction;
transaction.Dispose();
} }

最终总结一下:

1.查询无需事务;

2.涉汲执行增、删、改的SQL命令时,应考虑是否需要确保执行数据的一致性,若需要则必需使用事务,否则可以采取默认方式;

3.在同一个DB服务器中,尽可能的使用本地事务,跨多个DB服务器中,需要使用分布式事务;

4.尽可能的缩小事务的使用范围,避免出现多层级的嵌套事务;

5.若需要使用分布式事务,在WINDOWS下需要开启MS DTC服务(分布式事务管理器)

简述.NET事务应用原则的更多相关文章

  1. 一天五道Java面试题----第十天(简述Redis事务实现--------->负载均衡算法、类型)

    这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 1.简述Redis事务实现 2.redis集群方案 3.redis主从复制的核心原理 4.CAP理论,BASE理论 5.负 ...

  2. 数据库ACID操作---事务四原则

    事务操作四原则: 1>原子性:简单来说——整个事务操作如同原子已经是物理上最小的单位,不可分离事务操作要么一起成功,要么一起失败. 2>一致性:倘若事务操作失败,则回滚事务时,与原始状态一 ...

  3. 简述Spring事务有几种管理方法,写出一种配置方式

    Spring事务有两种方式: 1.编程式事务:(代码中嵌入) 2.声明式事务:(注解,XML) 注解方式配置事务的方式如下: 首先,需要在applicationContext.xml中添加启动配置,代 ...

  4. [高性能MYSQL 读后随笔] 关于事务的隔离级别(一)

    一.锁的种类 MySQL中锁的种类很多,有常见的表锁和行锁,也有新加入的Metadata Lock等等,表锁是对一整张表加锁,虽然可分为读锁和写锁,但毕竟是锁住整张表,会导致并发能力下降,一般是做dd ...

  5. 【mysql】关于事务的隔离级别

    一.锁的种类 MySQL中锁的种类很多,有常见的表锁和行锁,也有新加入的Metadata Lock等等,表锁是对一整张表加锁,虽然可分为读锁和写锁,但毕竟是锁住整张表,会导致并发能力下降,一般是做dd ...

  6. 《高性能MySQL》读书笔记--锁、事务、隔离级别 转

    1.锁 为什么需要锁?因为数据库要解决并发控制问题.在同一时刻,可能会有多个客户端对表中同一行记录进行操作,比如有的在读取该行数据,其他的尝试去删除它.为了保证数据的一致性,数据库就要对这种并发操作进 ...

  7. Spring分布式事务实现概览

    分布式事务,一直是实现分布式系统过程中最大的挑战.在只有单个数据源的单服务系统当中,只要这个数据源支持事务,例如大部分关系型数据库,和一些MQ服务,如activeMQ等,我们就可以很容易的实现事务. ...

  8. .NET:分布式事务

    背景 分布式事务使用起来比较方便,不过也是有成本的,因此如果可以不用就尽量不用,比如:采用saga.如果采用了分布式事务的话,就需要对分布式事务相关的几个概念有所了解. 分布式事务 相关角色: 事务发 ...

  9. 07_Redis事务

    [简述] 事务是指一系列的操作步骤,着一些列的操作步骤,要么完全地执行,要不完全地不执行. 比如微博中: A用户关注了B用户,那么A的关注列表里就会有B用户,B用户的粉丝列表里就会有A用户. 这个关注 ...

随机推荐

  1. 系统吞吐量(TPS)、用户并发量、性能测试概念和公式

    分享一个概念: http://www.ha97.com/5095.html

  2. The Myths about Transactions (ACID) and NoSQL

    There has been widespread characterization of one of the major distinctions between NoSQL and tradit ...

  3. Wishart distribution

    Introduction In statistics, the Wishart distribution is generalization to multiple dimensions of the ...

  4. MySQL 数据库事务与复制

    好久没有写技术文章了,因为一直在思考 「后端分布式」这个系列到底怎么写才合适. 最近基本想清楚了,「后端分布式」包括「分布式存储」和 「分布式计算」两大类. 结合实际工作中碰到的问题,以寻找答案的方式 ...

  5. jQuery 2.0.3 源码分析 Deferred(最细的实现剖析,带图)

    Deferred的概念请看第一篇 http://www.cnblogs.com/aaronjs/p/3348569.html ******************构建Deferred对象时候的流程图* ...

  6. JavaScript异步编程原理

    众所周知,JavaScript 的执行环境是单线程的,所谓的单线程就是一次只能完成一个任务,其任务的调度方式就是排队,这就和火车站洗手间门口的等待一样,前面的那个人没有搞定,你就只能站在后面排队等着. ...

  7. Redhat环境下编译安装Google Bazel

    Redhat环境下编译安装bazel 作者:Jack47 目前Google Bazel没有提供各个操作系统下的二进制安装包,只提供源代码,需要我们自己编译安装,详情可以见我翻译的中文版Google B ...

  8. 基于Quick-cocos2d-x的资源更新方案 一

    图片来自网络 思绪何来 昨天写了一篇关于更新方案的理论 游戏开发:通过路径搜索优先级来进行补丁升级(从端游到手游) 今天继续细化一下 由于新项目采用的是Quick-cocos2d-x,那我就直接给出我 ...

  9. 飞鱼(FlyFish)——便捷的原型在线制作工具

    关于项目原型制作,小菜先前写过一篇文章<FastUI快速界面原型制作工具>,只不过那个是用C#写的原型制作工具,但是感觉用C#写起来比较费力,而且也不太好用,经过高人指点,茅塞顿开,决定重 ...

  10. 【Paddy】如何将物理表分割成动态数据表与静态数据表

    前言 一般来说,物理表的增.删.改.查都受到数据量的制约,进而影响了性能. 很多情况下,你所负责的业务关键表中,每日变动的数据库与不变动的数据量比较,相差非常大. 这里我们将变动的数据称为动态数据,不 ...