默认情况当你执行SaveChanges()的时候(insert update delete)来操作数据库时,Entity Framework会把这个操作包装在一个事务里,当操作结束后,事务也结束了。

EF6中的 Database.ExecuteSqlCommand()也会启用一个事务,事务的隔离级别是默认级别(Read Commited)。

虽然这种框架默认的事务处理机制对于大多数情况下已经够用了,但是是EF6为我们提供了API,让我们能够更加灵活地对自己代码中的事务进行控制。

一、在EF中使用事务

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Entity;
  4. using System.Data.SqlClient;
  5. using System.linq;
  6. using System.Transactions;
  7. namespace TransactionsExamples
  8. {
  9. class TransactionsExample
  10. {
  11. static void StartOwnTransactionWithinContext()
  12. {
  13. using (var context = new BloggingContext())
  14. {
  15. using (var dbContextTransaction = context.Database.BeginTransaction())
  16. {
  17. try
  18. {
  19. context.Database.ExecuteSqlCommand(
  20. @"UPDATE Blogs SET Rating = 5" +
  21. " WHERE Name LIKE '%Entity Framework%'"
  22. );
  23. var query = context.Posts.Where(p => p.Blog.Rating >= 5);
  24. foreach (var post in query)
  25. {
  26. post.Title += "[Cool Blog]";
  27. }
  28. context.SaveChanges();
  29. dbContextTransaction.Commit();
  30. }
  31. catch (Exception)
  32. {
  33. dbContextTransaction.Rollback();
  34. }
  35. }
  36. }
  37. }
  38. }
  39. }

上面通过一个using语句块把要使用事务的操作起来,调用context.Database.BeginTransaction()启动一个事务,最后分别通过dbContextTransaction.Commit();和dbContextTransaction.Rollback();来提交或回滚事务。

注意:开启一个事务需要事务所有在的数据库链接是打开的,因此当所在数据库链接没有打开时Database.BeginTransaction()就会打开一个数据库链接。上面调用context.Database.BeginTransaction()是没有参数的,你可以调用这个BeginTransaction()其它重载函数来控制事务的隔离级别,如果没传参数将会使用默认的隔离级别。

二、传递一个已存在的事务

EF中可以传递一个存在的事务给context:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Entity;
  4. using System.Data.SqlClient;
  5. using System.Linq;
  6. sing System.Transactions;
  7. namespace TransactionsExamples
  8. {
  9. class TransactionsExample
  10. {
  11. static void UsingExternalTransaction()
  12. {
  13. using (var conn = new SqlConnection("..."))
  14. {
  15. conn.Open();
  16. using (var sqlTxn = conn.BeginTransaction(System.Data.IsolationLevel.Snapshot))
  17. {
  18. try
  19. {
  20. var sqlCommand = new SqlCommand();
  21. sqlCommand.Connection = conn;
  22. sqlCommand.Transaction = sqlTxn;
  23. sqlCommand.CommandText =
  24. @"UPDATE Blogs SET Rating = 5" +
  25. " WHERE Name LIKE '%Entity Framework%'";
  26. sqlCommand.ExecuteNonQuery();
  27. using (var context =
  28. new BloggingContext(conn, contextOwnsConnection: false))
  29. {
  30. context.Database.UseTransaction(sqlTxn);
  31. var query = context.Posts.Where(p => p.Blog.Rating >= 5);
  32. foreach (var post in query)
  33. {
  34. post.Title += "[Cool Blog]";
  35. }
  36. context.SaveChanges();
  37. }
  38. sqlTxn.Commit();
  39. }
  40. catch (Exception)
  41. {
  42. sqlTxn.Rollback();
  43. }
  44. }
  45. }
  46. }
  47. }
  48. }

三、TransactionScope事务

EF中让多个数据库操作作为一个整体的事务来处理除了上面使用事务传递来实现外,还可以利用TransactionScope对象来处理,如下:

  1. using System.Collections.Generic;
  2. using System.Data.Entity;
  3. using System.Data.SqlClient;
  4. using System.Linq;
  5. using System.Transactions;
  6. namespace TransactionsExamples
  7. {
  8. class TransactionsExample
  9. {
  10. static void UsingTransactionScope()
  11. {
  12. using (var scope = new TransactionScope(TransactionScopeOption.Required))
  13. {
  14. using (var conn = new SqlConnection("..."))
  15. {
  16. conn.Open();
  17. var sqlCommand = new SqlCommand();
  18. sqlCommand.Connection = conn;
  19. sqlCommand.CommandText =
  20. @"UPDATE Blogs SET Rating = 5" +
  21. " WHERE Name LIKE '%Entity Framework%'";
  22. sqlCommand.ExecuteNonQuery();
  23. using (var context =
  24. new BloggingContext(conn, contextOwnsConnection: false))
  25. {
  26. var query = context.Posts.Where(p => p.Blog.Rating > 5);
  27. foreach (var post in query)
  28. {
  29. post.Title += "[Cool Blog]";
  30. }
  31. context.SaveChanges();
  32. }
  33. }
  34. scope.Complete();
  35. }
  36. }
  37. }
  38. }

注意:上面提交事务是通过TransactionScope实例的Complete方法来提交的。

可以看到使用TransactionScope使我们代码简化了不少,但是要注意的是TransactionScope也有一些限制:

1、需要NET 4.5.1及以上

2、不能和Database.UseTransaction()方式结合起来使用

3、sql语句中不能有DLL操作

4、不能在云场景中使用,除非你保证只有一个数据库连接。(支场景中不支持分布式事务)

EF6中使用事务的方法的更多相关文章

  1. EF6 中tracking log使用方法总结

    先上一段最近项目中的代码,此代码可以放到自己项目中的dbContext中 public override Task<int> SaveChangesAsync() { List<Au ...

  2. 在Hibernate中分别使用JDBC和JTA事务的方法

    在Hibernate中使用JDBC事务 Hibernate对JDBC进行了轻量级的封装,它本身在设计时并不具备事务处理功能.Hibernate将底层的JDBCTransaction或JTATransa ...

  3. 在MySQL中设置事务隔离级别有2种方法:

    在MySQL中设置事务隔离级别有2种方法: 1 在my.cnf中设置,在mysqld选项中如下设置 [mysqld] transaction-isolation = READ-COMMITTED 2 ...

  4. @Transactional 同一个类中无事务方法a()内部调用有事务方法b()的问题

    https://blog.csdn.net/u010235716/article/details/90171802 1. 事务的4种特性       序号 参数 含义1 原子性(Atomicity) ...

  5. Entity Framework入门教程(19)---EF中使用事务

    EF中使用事务 这节介绍EF6中事务的使用.EF core中事务的使用方式和EF6中一模一样. 1.EF中的默认的事务 默认情况下,当我们执行一个SaveChanges()方法时就会新建了一个事务,然 ...

  6. 数据库事务及其EF中如何处理事务

    一.基础知识 1)         使用事务级别ReadUnCommited 会产生脏读现像,意味着读取到的为UnCommited(未提交)的数据.怎么理解呢?在使用该隔离级别的事务开始后.更新了数据 ...

  7. 存储过程中使用事务,sql server 事务,sql事务

    一.存储过程中使用事务的简单语法       在存储过程中使用事务时非常重要的,使用数据可以保持数据的关联完整性,在Sql server存储过程中使用事务也很简单,用一个例子来说明它的语法格式: 代码 ...

  8. 【MySQL】漫谈MySQL中的事务及其实现

    最近一直在做订单类的项目,使用了事务.我们的数据库选用的是MySQL,存储引擎选用innoDB,innoDB对事务有着良好的支持.这篇文章我们一起来扒一扒事务相关的知识. 为什么要有事务? 事务广泛的 ...

  9. Abp公共连接和事务管理方法

    Conection 和事务管理在使用数据库的应用中是一个最重要的概念.当你打开一个连接,开始一个事务,如何来处理这些连接等等. 您也许知道,.NET使用了连接池.所以,创建一个连接实际上是从连接池里得 ...

随机推荐

  1. 0 can't find referenced pointcut declarePointExpress

    今天在用SpringAOP 的 @pointCut 的时候报错 Exception in thread "main" org.springframework.beans.facto ...

  2. GCD之线程挂起与恢复

    我们可以使用dispatch_suspend函数暂停一个queue以阻止它执行block对象;使用dispatch_resume函数继续dispatch queue.调用dispatch_suspen ...

  3. oracle数据库使用心得之与SQL serve数据库的差异

    网上对于SQL数据库的使用比较详细,但是对于Oracle的使用比较少,本文特别适合学过SQL数据库但是工程需要使用Oracle数据的编程人员查看, 时间匆忙,文章可能写得不够详细,希望有人指出错误或者 ...

  4. Apache Spark 2.2.0 中文文档 - SparkR (R on Spark) | ApacheCN

    SparkR (R on Spark) 概述 SparkDataFrame 启动: SparkSession 从 RStudio 来启动 创建 SparkDataFrames 从本地的 data fr ...

  5. GCD SUM 强大的数论,容斥定理

    GCD SUM Time Limit: 8000/4000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) SubmitStatu ...

  6. [Tjoi2013]循环格

    [Tjoi2013]循环格 2014年3月18日1,7500 Description Input 第一行两个整数R,C.表示行和列,接下来R行,每行C个字符LRUD,表示左右上下. Output 一个 ...

  7. Centos7 创建本地 docker 仓库极其遇到的问题

    环境安装: VirtualBox 安装 Centos7 安装 docker 1. 配置私有仓库和客户端地址 私有仓库:192.168.1.104 客户端:192.168.1.103 通过 Centos ...

  8. 管中窥豹——从OVS看SDN

    网络虚拟化是当前云计算最重要的特点之一,打通租户网络之间互通以及访问控制策略,最重要的是满足租户之间的网络隔离,这才是云计算网络的特点.而SDN的产生则是在网络虚拟化中,将控制面和业务面分离,控制面只 ...

  9. iOS在类内部怎么访问实例变量比较好?

    OC在类文件的内部访问实例变量,有直接访问和使用getter/setter方法访问两种方式,它们的区别有: 1.直接访问不经过OC的方法分发(method dispatch),所以访问速度比较快,在这 ...

  10. 从实践的角度理解cookie的几个属性

    cookie的处理流程大致分为以下几步: 1.浏览器初次请求服务器. 2.服务器认为有必要设置cookie,通过响应报文首部:Set-Cookie告知浏览器,cookie的内容. 3.浏览器本地保存( ...