Entity Framework入门教程(19)---EF中使用事务
EF中使用事务
这节介绍EF6中事务的使用。EF core中事务的使用方式和EF6中一模一样。
1.EF中的默认的事务
默认情况下,当我们执行一个SaveChanges()方法时就会新建了一个事务,然后将context中的CUD操作都在这个事务中进行。Context中有多个SaveChanges()时,每一个SaveChanges()都会执行一个单独的事务。一个栗子:
using (var context = new SchoolContext())
{
context.Database.Log = Console.Write; var standard = context.Standards.Add(new Standard() { StandardName = "1st Grade" }); context.Students.Add(new Student()
{
FirstName = "Rama",
StandardId = standard.StandardId
}); context.SaveChanges(); context.Courses.Add(new Course() { CourseName = "Computer Science" });
context.SaveChanges();
}
上边的代码执行结果如下:

从上边的栗子我们可以清楚地看到每个SaveChanges()方法都开启了一个事务。这时有一个问题:有没有什么办法让多个SaveChanges()在一个事务中执行呢?这样的话就可以减少事务创建、开启进而提升性能了。
2.一个事务执行多个SaveChanges()方法
EF6和EF core中提供了两种方法实现在一个事务中执行多个SaveChanges()方法。
① DbContext.Database.BeginTrasaction():新建一个事务,在新建的事务内进行context.SaveChanges()
②DbContext.Database.UseTransaction(trans):使用一个context作用域外的现有的事务,多个context都可以在通过这个事务一起提交。
1.DbContext.Database.BeginTrasaction()
一个栗子:
using (var context = new SchoolContext())
{
context.Database.Log = Console.Write; using (DbContextTransaction transaction = context.Database.BeginTransaction())
{
try
{
var standard = context.Standards.Add(new Standard() { StandardName = "1st Grade" }); context.Students.Add(new Student()
{
FirstName = "Rama",
StandardId = standard.StandardId
});
context.SaveChanges();
// 第一个SaveChanges()方法后抛出异常
throw new Exception(); context.Courses.Add(new Course() { CourseName = "Computer Science" });
context.SaveChanges(); transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
Console.WriteLine("Error occurred.");
}
}
}
执行结果:

我们可以看到所有的SaveChanges()都被回滚了。如果把抛出异常的代码注释掉那么执行效果如下:

2.DbContext.Database.UseTransaction(trans)
使用DbContext.Database.UseTransaction(trans),我们通过参数传入的是一个作用域外的事务,注意:这里EF不会再新建内置的事务,而是使用通过参数传入的事务。
一个栗子:
private static void Main(string[] args)
{
string providerName = "System.Data.SqlClient";
string serverName = ".";
string databaseName = "SchoolDB"; // 目标数据库
SqlConnectionStringBuilder sqlBuilder =new SqlConnectionStringBuilder();
sqlBuilder.DataSource = serverName;
sqlBuilder.InitialCatalog = databaseName;
sqlBuilder.IntegratedSecurity = true; using (SqlConnection con = new SqlConnection(sqlBuilder.ToString()))
{
con.Open();
//在DbContext作用域外新建一个事务
using (SqlTransaction transaction = con.BeginTransaction())
{
try
{
//使用上边的创建的事务
using (SchoolContext context = new SchoolContext(con, false))
{
context.Database.UseTransaction(transaction); context.Students.Add(new Student() { Name = "Ravi" });
context.SaveChanges();
} using (SchoolContext context = new SchoolContext(con, false))
{
context.Database.UseTransaction(transaction); context.Grades.Add(new Standard() { GradeName = "Grade 1", Section = "A" });
context.SaveChanges();
}
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback(); Console.WriteLine(ex.InnerException);
}
}
}
}
EF系列目录链接:Entity Franmework系列教程汇总
Entity Framework入门教程(19)---EF中使用事务的更多相关文章
- Entity Framework入门教程(3)---EF中的上下文简介
1.DbContext(上下文类) 在DbFirst模式中,我们添加一个EDM(Entity Data Model)后会自动生成一个.edmx文件,这个文件中包含一个继承DbContext类的上下文实 ...
- Entity Framework入门教程(4)---EF中的实体关系
这一节将总结EF是怎么管理实体之间的关系.EF与数据库一样支持三种关系类型:①一对一 ,②一对多,③多对多. 下边是一个SchoolDB数据库的实体数据模型,图中包含所有的实体和各个实体间的关系.通过 ...
- Entity Framework入门教程(5)---EF中的持久化场景
EF中的持久性场景 使用EF实现实体持久化(保存)到数据库有两种情况:在线场景和离线场景. 1.在线场景 在线场景中,context是同一个上下文实例(从DbContext派生),检索和保存实体都通过 ...
- Entity Framework入门教程(13)---EF中的高并发
EF中的高并发 这里只介绍EF6中database-first开发方案的高并发解决方案,code-first开发方案中的高并发会在以后的EF CodeFirst系列中介绍. EF默认支持乐观并发:我们 ...
- Entity Framework入门教程(7)--- EF中的查询方法
这里主要介绍两种查询方法 Linq to entity(L2E)和Sql 1.L2E查询 L2E查询时可以使用linq query语法,或者lambda表达式,默认返回的类型是IQueryable,( ...
- Entity Framework入门教程(2)---EF工作流程
EF工作流程 1.EF基本CRUD流程 下边的图就可以很清晰地展示EF的CRUD操作的基本工作流程: 这里做一个EF CRUD操作的简单总结:1.定义模型:这是EF工作的前提,定义模型包括定义领域类( ...
- Entity Framework入门教程(6)--- 在线场景中保存数据
在线场景中保存数据 在线场景中保存实体数据是一项相当容易的任务,因为使用的是同一个context,这个context会自动跟踪所有实体发生的更改. 下图说明了在线场景中的CUD(创建,更新,删除)操作 ...
- Entity Framework入门教程(11)---EF6中的异步查询和异步保存
EF6中的异步查询和异步保存 在.NET4.5中介绍了异步操作,异步操作在EF中也很有用,在EF6中我们可以使用DbContext的实例进行异步查询和异步保存. 1.异步查询 下边是一个通过L2E语法 ...
- Entity Framework入门教程(12)--- EF进行批量添加/删除
EF6添加了批量添加/删除实体集合的方法,我们可以使用DbSet.AddRange()方法将实体集合添加到上下文,同时实体集合中的每一个实体的状态都标记为Added,在执行SaveChange()方法 ...
随机推荐
- Bootstrap Multiselect插件使用步骤以及常见参数配置介绍
Multiselect是基于jQuery插件的,它可以以下拉列表的形式为用户提供选择内容,能进行单选或者多选.它应用的主要步骤如下: 一,引入需要的相关js和css文件 既然是Bootstrap插件, ...
- Elixir 简介
概述 Elixir 是一种基于 Erlang 虚拟机的函数式,面向并行的通用语言, 它是一门通用语言,所以不仅可以用在擅长的高可用,高并发场景下,也可以用在 web 开发等场景下. Erlang 诞生 ...
- jsplumb 中文基础教程
jsplumb 中文基础教程 https://github.com/wangduanduan/jsplumb-chinese-tutorial
- P1744 采购特价商品 题解(讲解图论)
图论的超级初级题目(模板题) 最短路径的模板题 图是啥?(白纸上的符号?) 对于一个拥有n个顶点的无向连通图,它的边数一定多于n-1条.若从中选择n-1条边,使得无向图仍然连通,则由n个顶点及这 n- ...
- 《Linux/UNIX系统编程手册》第63章 IO多路复用、信号驱动IO以及epoll
关键词:fasync_helper.kill_async.sigsuspend.sigaction.fcntl.F_SETOWN_EX.F_SETSIG.select().poll().poll_wa ...
- 通过Docker发布RestAPI遇到的种种问题
目标:发布一个分词API 问题1:Docker外无法访问API 原因: Docker映射的地址是0.0.0.0:8888端口,而flask启动的时候默认地址是127.0.0.1:5000,需要手动配置 ...
- 如何卸载VS 2017之前版本比如VS 2013、VS2015、 VS vNext?
前言 大学专业为软件工程,进入大学之后才知道这个专业需要用到笔记本,我的笔记本配置为I3,内存4个G,已经有大几年了,中间坏了修了一次一直用到现在,这个笔记本还是我哥打工过年回来身上仅有的三四千块钱所 ...
- windows service承载的web api宿主搭建(Microsoft.Owin+service)
今天突然想起改良一下以前搭建的“windows service承载的web api”服务,以前也是直接引用的类库,没有使用nuget包,时隔几年应该很旧版本了吧.所以本次把需要nuget获取的包记录一 ...
- OracleSql语句学习(一)
--SQL语句本身是不区分大小写的,每个关键字用空格隔开,为了增加可读性,退出所有关键字--全部大写,非关键字都小写SELECT SYSDATE FROM dual--创建表CREATE TABLE ...
- OC调用c++函数
1.调用的时候我明明改成了 .mm , 也添加了libstdc++.dylib 调用自己(xcode )写的(cocoa static lib )c++ ,编译总是报找不到库里的函数, 最后我在 ...