数据库事务及其EF中如何处理事务
一、基础知识
1) 使用事务级别ReadUnCommited 会产生脏读现像,意味着读取到的为UnCommited(未提交)的数据。怎么理解呢?在使用该隔离级别的事务开始后。更新了数据库某一行的数据,但是事务的工作量比较大,后续还有一大堆代码还没执行完呢。不巧的是有个哥们过来读数据了,这个时候读到的就是未提交的值,如果后继工作一切正常,也没什么影响。一旦后面的代码执行中出错,就会产生不一致的错误,适用于对事务极度自信的情况下,特点为可读不可改。关于不可改需解释一下,MS SQL中一条语句为最基本的执行单元了,如果一个事务中,对同条数据的更新语句未Commited的情况下,其它事务是需要等待的。
2) 使用事务级别ReadCommited 会消除脏读现像,意味着读取到的为Commited(已提交)的数据。在使用该隔离级别的事务开始后,除了该事务其它的查询均会一直等待直到该事务提交。特点为不可读不可改,
3) 使用事务级别Repeatable Read,可重复读。它不会像ReadCommited一样阻止Select查询,但它会阻止Update语句。使用该隔离级别的事务开始后,会阻止其它事务更改查询。但依然可以新增数据。
4) 使用事务级别Serializable 最严的一种了,与Repeatable Read相比就是在这种级别下不能新增数据。
5) 下表为简单说明
其中增删除改查为其它事务中对已在事务中的数据行进行增删改查的可能行性,其中删,改,查操作多个事务中的同一条数据。√指该隔离级别下操作可未被阻塞可立即响应。
|
隔离级别 |
增(其他事务) |
删(其他事务) |
改(其他事务) |
查(其他事务) |
脏读 |
读提交 |
可重复读 |
幻影读 |
数据过期 |
|
ReadUnCommited |
√ |
× |
× |
√ |
√ |
× |
× |
√ |
√ |
|
ReadCommited |
√ |
× |
× |
× |
× |
√ |
× |
√ |
× |
|
Repeatable Read |
√ |
× |
× |
√ |
× |
√ |
√ |
√ |
√ |
|
Serializable |
× |
× |
× |
√ |
× |
√ |
√ |
× |
√ |
二、C#中的事务
1) ADO.NET中的事务与EF中的事务,它们是一类事物。可以说是同一个东西,均为封装了 SQL语句中的 Begin Tran Commit等。
2) 分布式事务TranscationCope需引用System.data.Transcations.dll才能使用
3) 分布式事务与事务二者区别,主要区别在于前者用于一个数据连接中控制数据一致性,后者在多个数据库连接中控制数据一致性,如果不能理解,可以记忆为一个数据库使用事务用前者,多个数据库中使用事务用后者,如果在一个数据连接中使用TranscationCope,可以把它为理解为简化版的事务,因为它只有Complete方法。
4) 注意TranscationCope进行多事务协调时需安装与设置MSDTC组件。
5) 并行事务:指在同一个DBConnection中启用二个事务,这个不被ADO.NET与EF支持(目前),如果程序运行过程中出现了 Connection不支持并行事务的时候,检查一下是否在一个数据库连接中使用了二个事务。
三、事务的应用与验证。
1) 下面依次验证(末完成)
验证时注意事项:连接字符串中设置 Pooling = False 既关掉数据连接池,特别是多次测试之后会有点小问题干扰结论。;如果需要验证多个事务进行引发的异常还是阻塞进程,需要把超时时间设置为更多一些超过程序预计运行时间。EF建议大家使用EF6.0,在低版本的 EF 中不能指定SaveChanges时使用的事务。
验证时使用3个线程向同一表中插入10条数据,如果顺序插入,表明事务是顺序执行,下面上代码
class Program
{
static string connectionString = "server=127.0.0.1;database=xxxxxx;user=sa;password=xxxxxx;Pooling=False";
static System.Data.IsolationLevel tranLevel = System.Data.IsolationLevel.ReadUncommitted;
static string commandText = "update [Locker] set [id] = 100" ; static void Main(string[] args)
{
ClearTestData();
tranLevel = System.Data.IsolationLevel.ReadUncommitted;
commandText = "update [Locker] set [id] = 100";
Thread th1 = new Thread(new ThreadStart(() =>
{
test();
})); Thread th2 = new Thread(new ThreadStart(() =>
{
test(); }));
Thread th3 = new Thread(new ThreadStart(() =>
{
test(); }));
th1.Name = "线程1";
th2.Name = "线程2";
th3.Name = "线程3";
th2.Start();
th3.Start();
th1.Start();
Console.ReadLine();
} static void test()
{
using (var db = new SupplierPortalEntities())
{
var connection = db.Database.Connection;
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
var tran = connection.BeginTransaction(tranLevel);
try
{
db.Database.UseTransaction(tran);
var command = commandText;
db.Database.ExecuteSqlCommand(command); for (int i = 0; i < 20; i++)
{
Random r = new Random();
var t = new TranLocker();
t.Content = Thread.CurrentThread.Name;
db.TranLocker.Add(t);
Console.WriteLine("线程{0}加入数据 - lockid: {1}", Thread.CurrentThread.Name, t.LockID);
Thread.Sleep(50);
}
db.SaveChanges();
//if (Thread.CurrentThread.Name.EndsWith("3")) //引发一个异常 .
//{
// throw new Exception("3为故障码");
//}
tran.Commit();
Console.WriteLine("线程{0}:事务已提交", Thread.CurrentThread.Name);
}
catch (Exception er)
{
tran.Rollback();
Console.WriteLine("线程{0}:发生错误,事务已回滚:{1}", Thread.CurrentThread.Name, er.Message);
}
}
} static void ClearTestData()
{
//清除数据
var connClearInsertDatas = new SqlConnection(connectionString);
connClearInsertDatas.Open();
var cmd = connClearInsertDatas.CreateCommand();
cmd.CommandText = "delete from TranLocker";
cmd.ExecuteNonQuery();
connClearInsertDatas.Close();
}
}
数据库事务及其EF中如何处理事务的更多相关文章
- Entity Framework入门教程(19)---EF中使用事务
EF中使用事务 这节介绍EF6中事务的使用.EF core中事务的使用方式和EF6中一模一样. 1.EF中的默认的事务 默认情况下,当我们执行一个SaveChanges()方法时就会新建了一个事务,然 ...
- 重新学习MySQL数据库9:Innodb中的事务隔离级别和锁的关系
重新学习MySQL数据库9:Innodb中的事务隔离级别和锁的关系 Innodb中的事务隔离级别和锁的关系 前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁 ...
- 事务的隔离级别,mysql中开启事务、django中开启事务
目录 一.事务的特性 二.数据库中开启事务 三.Django中开启事务的两种方式 第一种 第二种 四.事务的隔离级别 隔离级别 如何查看mysql隔离级别? 修改事务的隔离级别 隔离级别解释 read ...
- EF中使用事务
using (var db = new dbEntities()) { //第一个坑,需要手动open db.Database.Connection.Open(); using (var tran = ...
- 事务——sql server中的事务应用举例
sql中事务只针对一个update,delete,insert语句,如果一段程序中有超过一个这样的语句,就需要每个都判断是否出错,否则就会出现若干我们不希望的情形出现,举例如下(表结构见最后): 1, ...
- 阶段3 1.Mybatis_07.Mybatis的连接池及事务_6 mybatis中的事务原理和自动提交设置
在实际的开发中,建议使用连接池的形式. JNDI的资料 H:\BaiDu\黑马传智JavaEE57期 2019最新基础+就业+在职加薪\讲义+笔记+资料\主流框架\31.会员版(2.0)-就业课(2. ...
- 在EF中正确的使用事务
1.EF中使用事务: using (TransactionScope tran = new TransactionScope()) { try { using(var _context = new D ...
- 代码中添加事务控制 VS(数据库存储过程+事务) 保证数据的完整性与一致性
做人事档案的系统考虑到数据的安全性与一致性,毕竟是要对外上线.真正投入使用的项目,数据库的可靠性与安全性上我们开发人员要考虑的就很多了,记得做机房收费系统时注册新卡是自己为了简单,写成了一个存储过程( ...
- 一步步学习EF Core(2.事务与日志)
前言 上节我们留了一个问题,为什么EF Core中,我们加载班级,数据并不会出来 其实答案很简单,~ 因为在EF Core1.1.2 中我们在EF6.0+中用到的的延迟加载功能并没有被加入,不过在EF ...
随机推荐
- [NOIP2014提高组]联合权值
题目:洛谷P1351.Vijos P1906.codevs3728.UOJ#16. 题目大意:有一个无向连通图,有n个点n-1条边,每个点有一个权值$W_i$,每条边长度为1.规定两个距离为2的点i和 ...
- python Web抓取(二)selenium模块的使用、对浏览器的按键操作及错误处理
建议以下帖子: 教你在Windows上搭建Python+Selenium环境:https://blog.csdn.net/huilan_same/article/details/52888262 py ...
- 快速创建WCF服务和svcutil.exe工具使用
先简单的创建WCF服务: 系统会自动加上IService1接口 和 Service1 实现类 分别在IService1 和Service1 加上2段代码. [ServiceContract] publ ...
- 05-数据类型转换(bool转换)
05-数据类型转换(bool转换)
- 洛谷 P1293 班级聚会
P1293 班级聚会 题目描述 毕业25年以后,我们的主人公开始准备同学聚会.打了无数电话后他终于搞到了所有同学的地址.他们有些人仍在本城市,但大多数人分散在其他的城市.不过,他发现一个巧合,所有地址 ...
- POJ 3450--Corporate Identity【KMP && 枚举】
Corporate Identity Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 5696 Accepted: 207 ...
- 记录一下sql两个表关联的查询使用方法
SELECT * FROM t_yymp_user_info where user_id = (select b.user_id from t_yymp_auth_role as a,t_yymp_a ...
- 反斜杠处理函数addslashes()和stripslashes()
addslashes():对输入字符串中的某些预定义字符前添加反斜杠,这样处理是为了数据库查询语句等的需要.这些预定义字符是:单引号 (') ,双引号 (") ,反斜杠 (\) ,NULL. ...
- React开发实时聊天招聘工具 -第二章
2-1 介绍React开发环境 npm install -g create-react-app xxx npm run eject 来配置webpack 2-2 ES6常用语法 其他 还有一些特性 ...
- WebAssembly学习(三):AssemblyScript - TypeScript到WebAssembly的编译
虽然说只要高级语言能转换成 LLVM IR,就能被编译成 WebAssembly 字节码,官方也推荐c/c++的方式,但是让一个前端工程师去熟练使用c/c++显然是有点困难,那么TypeScript ...