EF6中使用事务的方法
默认情况当你执行SaveChanges()的时候(insert update delete)来操作数据库时,Entity Framework会把这个操作包装在一个事务里,当操作结束后,事务也结束了。
EF6中的 Database.ExecuteSqlCommand()也会启用一个事务,事务的隔离级别是默认级别(Read Commited)。
虽然这种框架默认的事务处理机制对于大多数情况下已经够用了,但是是EF6为我们提供了API,让我们能够更加灵活地对自己代码中的事务进行控制。
一、在EF中使用事务
- using System;
- using System.Collections.Generic;
- using System.Data.Entity;
- using System.Data.SqlClient;
- using System.linq;
- using System.Transactions;
- namespace TransactionsExamples
- {
- class TransactionsExample
- {
- static void StartOwnTransactionWithinContext()
- {
- using (var context = new BloggingContext())
- {
- using (var dbContextTransaction = context.Database.BeginTransaction())
- {
- try
- {
- context.Database.ExecuteSqlCommand(
- @"UPDATE Blogs SET Rating = 5" +
- " WHERE Name LIKE '%Entity Framework%'"
- );
- var query = context.Posts.Where(p => p.Blog.Rating >= 5);
- foreach (var post in query)
- {
- post.Title += "[Cool Blog]";
- }
- context.SaveChanges();
- dbContextTransaction.Commit();
- }
- catch (Exception)
- {
- dbContextTransaction.Rollback();
- }
- }
- }
- }
- }
- }
上面通过一个using语句块把要使用事务的操作起来,调用context.Database.BeginTransaction()启动一个事务,最后分别通过dbContextTransaction.Commit();和dbContextTransaction.Rollback();来提交或回滚事务。
注意:开启一个事务需要事务所有在的数据库链接是打开的,因此当所在数据库链接没有打开时Database.BeginTransaction()就会打开一个数据库链接。上面调用context.Database.BeginTransaction()是没有参数的,你可以调用这个BeginTransaction()其它重载函数来控制事务的隔离级别,如果没传参数将会使用默认的隔离级别。
二、传递一个已存在的事务
EF中可以传递一个存在的事务给context:
- using System;
- using System.Collections.Generic;
- using System.Data.Entity;
- using System.Data.SqlClient;
- using System.Linq;
- sing System.Transactions;
- namespace TransactionsExamples
- {
- class TransactionsExample
- {
- static void UsingExternalTransaction()
- {
- using (var conn = new SqlConnection("..."))
- {
- conn.Open();
- using (var sqlTxn = conn.BeginTransaction(System.Data.IsolationLevel.Snapshot))
- {
- try
- {
- var sqlCommand = new SqlCommand();
- sqlCommand.Connection = conn;
- sqlCommand.Transaction = sqlTxn;
- sqlCommand.CommandText =
- @"UPDATE Blogs SET Rating = 5" +
- " WHERE Name LIKE '%Entity Framework%'";
- sqlCommand.ExecuteNonQuery();
- using (var context =
- new BloggingContext(conn, contextOwnsConnection: false))
- {
- context.Database.UseTransaction(sqlTxn);
- var query = context.Posts.Where(p => p.Blog.Rating >= 5);
- foreach (var post in query)
- {
- post.Title += "[Cool Blog]";
- }
- context.SaveChanges();
- }
- sqlTxn.Commit();
- }
- catch (Exception)
- {
- sqlTxn.Rollback();
- }
- }
- }
- }
- }
- }
三、TransactionScope事务
EF中让多个数据库操作作为一个整体的事务来处理除了上面使用事务传递来实现外,还可以利用TransactionScope对象来处理,如下:
- using System.Collections.Generic;
- using System.Data.Entity;
- using System.Data.SqlClient;
- using System.Linq;
- using System.Transactions;
- namespace TransactionsExamples
- {
- class TransactionsExample
- {
- static void UsingTransactionScope()
- {
- using (var scope = new TransactionScope(TransactionScopeOption.Required))
- {
- using (var conn = new SqlConnection("..."))
- {
- conn.Open();
- var sqlCommand = new SqlCommand();
- sqlCommand.Connection = conn;
- sqlCommand.CommandText =
- @"UPDATE Blogs SET Rating = 5" +
- " WHERE Name LIKE '%Entity Framework%'";
- sqlCommand.ExecuteNonQuery();
- using (var context =
- new BloggingContext(conn, contextOwnsConnection: false))
- {
- var query = context.Posts.Where(p => p.Blog.Rating > 5);
- foreach (var post in query)
- {
- post.Title += "[Cool Blog]";
- }
- context.SaveChanges();
- }
- }
- scope.Complete();
- }
- }
- }
- }
注意:上面提交事务是通过TransactionScope实例的Complete方法来提交的。
可以看到使用TransactionScope使我们代码简化了不少,但是要注意的是TransactionScope也有一些限制:
1、需要NET 4.5.1及以上
2、不能和Database.UseTransaction()方式结合起来使用
3、sql语句中不能有DLL操作
4、不能在云场景中使用,除非你保证只有一个数据库连接。(支场景中不支持分布式事务)
EF6中使用事务的方法的更多相关文章
- EF6 中tracking log使用方法总结
先上一段最近项目中的代码,此代码可以放到自己项目中的dbContext中 public override Task<int> SaveChangesAsync() { List<Au ...
- 在Hibernate中分别使用JDBC和JTA事务的方法
在Hibernate中使用JDBC事务 Hibernate对JDBC进行了轻量级的封装,它本身在设计时并不具备事务处理功能.Hibernate将底层的JDBCTransaction或JTATransa ...
- 在MySQL中设置事务隔离级别有2种方法:
在MySQL中设置事务隔离级别有2种方法: 1 在my.cnf中设置,在mysqld选项中如下设置 [mysqld] transaction-isolation = READ-COMMITTED 2 ...
- @Transactional 同一个类中无事务方法a()内部调用有事务方法b()的问题
https://blog.csdn.net/u010235716/article/details/90171802 1. 事务的4种特性 序号 参数 含义1 原子性(Atomicity) ...
- Entity Framework入门教程(19)---EF中使用事务
EF中使用事务 这节介绍EF6中事务的使用.EF core中事务的使用方式和EF6中一模一样. 1.EF中的默认的事务 默认情况下,当我们执行一个SaveChanges()方法时就会新建了一个事务,然 ...
- 数据库事务及其EF中如何处理事务
一.基础知识 1) 使用事务级别ReadUnCommited 会产生脏读现像,意味着读取到的为UnCommited(未提交)的数据.怎么理解呢?在使用该隔离级别的事务开始后.更新了数据 ...
- 存储过程中使用事务,sql server 事务,sql事务
一.存储过程中使用事务的简单语法 在存储过程中使用事务时非常重要的,使用数据可以保持数据的关联完整性,在Sql server存储过程中使用事务也很简单,用一个例子来说明它的语法格式: 代码 ...
- 【MySQL】漫谈MySQL中的事务及其实现
最近一直在做订单类的项目,使用了事务.我们的数据库选用的是MySQL,存储引擎选用innoDB,innoDB对事务有着良好的支持.这篇文章我们一起来扒一扒事务相关的知识. 为什么要有事务? 事务广泛的 ...
- Abp公共连接和事务管理方法
Conection 和事务管理在使用数据库的应用中是一个最重要的概念.当你打开一个连接,开始一个事务,如何来处理这些连接等等. 您也许知道,.NET使用了连接池.所以,创建一个连接实际上是从连接池里得 ...
随机推荐
- 将数据转成JSON
前言 前面我们在使用Strus2的时候,Struts2自带了组件能够让JavaBean对象.集合转成是JSON,不用我们自己拼接-这是非常方便的.但是,我们不一定使用Struts2框架来做开发呀.因此 ...
- java基础知识4--数组的常用方法(Array)
先说一个idea编辑器的问题,编辑器的光标变成黑色光标无法移动,按一下insert键就好了. 数组是线性数据存储结构.它用牺牲自动扩展大小来换取与集合相比的唯一优势--查询效率的提升.本身是一种引用类 ...
- python实例编写(7)---测试报告与测试套件(多个py文件,1个py文件内多个用例)
一. 一个.py文件批量执行测试用例(一个.py文件下多个用例执行) 如果直接使用:unittest.main(),则按字母顺序执行, 对于前后之间又依赖关系的用例,需要按特定的顺序执行,则使用 s ...
- 时间效率:最小的K个数
输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. import java.util.ArrayList; import jav ...
- 利用ADO让普通人用excel读取oracle数据库表的通用办法
Ref:http://blog.csdn.net/iamlaosong/article/details/8465177 Excel通过ADO方式连接到Oracle并操作Oracle给那些编程能力不强的 ...
- CentOs下,配置tomcat支持https
网上此类教程一大堆,本文主要记录步骤和几个注意点. 首先,我们使用jdk的keytool生成证书.命令如下: p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: ...
- 翻译连载 | 第 9 章:递归(上)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇
原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...
- PYTHON 函数局部变量和全局变量
有这样一段PYTHON代码,从事C语言开发的人都知道,如果定义了全局变量,而函数内没有定义同名的函数变量的话,那么在函数内对该变量的赋值就是对全局变量空间数值的修改, 然后在PYTHON中却不尽相同, ...
- Mysql 基于 Amoeba 的 读写分离
首先说明一下amoeba 跟 MySQL proxy在读写分离的使用上面的区别: 在MySQL proxy 6.0版本 上面如果想要读写分离并且 读集群.写集群 机器比较多情况下,用mysql pro ...
- 变量的声明和定义以及extern的用法
变量的声明和定义以及extern的用法 变量的声明不同于变量的定义,这一点往往容易让人混淆. l 变量 ...