.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. 输入框三种输入方式(selenium webdriver 干货)

    在机票预定的页面,输入出发城市和到达城市输入框的时候, 发现直接使用sendkeys不好使, 大部分情况出现输入某城市后没有输入进去, 经过几天的研究,发现可以采取三种方式: 1. 先点击输入框,待弹 ...

  2. 游戏编程技巧 - Type Object

    Type Object 使用场景 你在制作一款和LOL类似的游戏,里面有许多英雄,因此你想建立一个英雄基类,然后把各种英雄都继承自该基类,这些英雄类都有生命值和攻击力等属性.每次策划想增加一个英雄,你 ...

  3. Java中@Override的作用

    @Override是伪代码,表示重写(当然不写也可以),不过写上有如下好处: 1.可以当注释用,方便阅读:2.编译器可以给你验证@Override下面的方法名是否是你父类中所有的,如果没有则报错.例如 ...

  4. Nova PhoneGap框架 第七章 设备事件处理

    我们的框架包含了几种设备事件的处理,目的是为了让我们的程序员更容易的完成代码.这些事件包括:回退键(Android)和横竖屏切换事件. 7.1 Android回退键 首先来说说回退键的事件处理.当用户 ...

  5. [ASP.NET MVC 小牛之路]07 - URL Routing

    我们知道在ASP.NET Web Forms中,一个URL请求往往对应一个aspx页面,一个aspx页面就是一个物理文件,它包含对请求的处理. 而在ASP.NET MVC中,一个URL请求是由对应的一 ...

  6. rem单位和em单位的使用

    今天弄了一点响应式的东西,本以为很快就可以弄好,结果还是绕晕了头,所以还是写下来方便下次看吧! 一开始我打算用百分比%来做响应式布局,后来算的很懵圈,就果断放弃了,哈哈是不是很明智. 接下来就是rem ...

  7. The replication agent has not logged a progress message in 10 minutes.

    打开Replication Monitor,在Subscription Watch List Tab中,发现有大量的status= “Performance critical” 的黄色Warning, ...

  8. 用Mindjet MindManager 15 打开文件后停止响应的解决方法

    这个是因为文件里面有很多规格不统一的注释(那个像小本子的图标[里面就是注释部分]),默认编码是utf-8的,如果不一样的话就会出现这个问题.网上大多数都是让咱们删掉注释再打开 弱弱的问一下,如果我都把 ...

  9. 【WP开发】记录屏幕操作

    在某些应用中,比如游戏,有时候需要将用户的操作记录下来.ScreenCapture类提供了这个功能.但必须注意的是:此屏幕记录功能只对当前应用程序的屏幕有效,即只有当前应用程序在前台运行时才有效. 与 ...

  10. Python第一天 - 函数

    ---恢复内容开始--- (一)定义一个函数 def 函数名(参数): 函数体 return 返回值 例: def mySum(x , y): return int(x)+int(y)print(my ...