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使用了连接池.所以,创建一个连接实际上是从连接池里得 ...
随机推荐
- web网站更换新域名
第一步.绑定新的域名到单独的空间 一般我们都是用的VPS或者不限制建站数量的虚拟主机,尽量的保持原有的IP不变,我这边在老站点同IP的VPS主机下新建一个新域名站点,这样我们可以确保原有的站点IP不变 ...
- cnblogs第一天
2017-08-25 21:27:16 今天算是真的下定决心要好好的去经营自己的博客了. flag也就不立了,毕竟,flag这种东西立了就是为了打脸的嘛....... 既然说是经营了,那必然是要认认真 ...
- mapreduce自定义排序(map端1.4步)
3 3 3 2 3 1 2 2 2 1 1 1 -----------------期望输出 1 1 2 1 2 2 3 1 3 2 3 3 将以上数据进行排序,排序规则是:按照第一列升序排序,如果第一 ...
- jdk版本切换
安装1.6/1.7/1.8版本的jdk 保存jdk的安装目录下的文件 卸载所有jdk 将jdk各个版本拷贝到一个文件夹下 配置环境变量 因为安装之后系统会有注册表之类的文件,单纯的修改环境是不会修改成 ...
- pycharm 2017新建文件添加编码方式等
file->setting->Editor->File and Code Templates->Python Script 添加 #!/usr/bin/python3# -*- ...
- SSH端口转发详解及实例
一.SSH端口转发简介 SSH会自动加密和解密所有SSH客户端与服务端之间的网络数据.但是,SSH还能够将其他TCP端口的网络数据通SSH链接来转发,并且自动提供了相应的加密及解密服务.这一过程也被叫 ...
- JAVA 反射(1)
getDeclaredField是可以获取一个类的所有字段. getField只能获取类的public 字段.
- WINDOWS XP中用命令行管理用户 net user命令
net user <username> [password or *] [/add] [options] [/domain] net user <username] /delete ...
- 对Item中定时器的理解
一.Diamond介绍 Diamond主要提供持久配置的发布和订阅服务,最大特点是结构简单,稳定可靠. 主要的使用场景:TDDL使用Diamond动态切换数据库,动态扩容等:业务使用Diamond推送 ...
- You Are the One DP
You Are the One Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Sub ...