默认情况当你执行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. 理解 IntelliJ IDEA 的项目配置和Web部署

    1.项目配置的理解 IDEA 中最重要的各种设置项,就是这个 Project Structre 了,关乎你的项目运行,缺胳膊少腿都不行.最近公司正好也是用之前自己比较熟悉的IDEA而不是Eclipse ...

  2. CSS3 box-sizing属性的应用

    在一个文档中,每个元素都被表示为一个矩形的盒子.盒子模型具有4个属性['外边距(margin)','边框(border)','内边距(padding)','内容(content)']. 我们要设置某个 ...

  3. Redis学习笔记之一 : 配置redis

    Redis 简介 Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库. Redis 与其他 key - value 缓存产品有以下三个特点: Redis支持数据的持久 ...

  4. Java平台与.Net平台在服务器端前景预测

    如果是服务器端, 毫无疑问C#是很难跟Java拼的. 就算将来,微软逆袭的机会也很渺茫了.就技术的先进性来说, Java平台是不如.Net平台, 但是, 程序员对于两个平台,直接接触的基本以语言为主, ...

  5. java 面向对象 2

    一.JAVA类的定义 JAVA里面有class关键字定义一个类,后面加上自定义的类名即可.如这里定义的person类,使用class person定义了一个person类,然后在person这个类的类 ...

  6. window、linux系统与linux服务器之间使用svn同步及自动部署代码的方法

    摘要: 在家用PC,在公司用办公电脑对一个项目的代码进行修改时,会遇到代码同步的问题.本文讲解了代码同步及自动部署的解决办法. 实现方法: 1.首先在linux服务器上和linux上安装svn(sud ...

  7. 我的第一个python web开发框架(3)——怎么开始?

    小白与小美公司经过几次接触商谈,好不容易将外包签订了下来,准备开始大干一场.不过小白由于没有太多的项目经验,学过python懂得python的基本语法,在公司跟着大家做过简单功能,另外还会一些HTML ...

  8. 【ASP.NET MVC】jqGrid 增删改查详解

    1   概述 本篇文章主要是关于JqGrid的,主要功能包括使用JqGrid增删查改,导入导出,废话不多说,直接进入正题. 2   Demo相关 2.1   Demo展示 第一部分 第二部分 2.2 ...

  9. ionic2+Angular2:套接口明细步骤,以登录功能为例

    1.在app.module.ts引用HttpModul,并在imports内引用.截图如下:   2.在src目录下新建http服务.命令行:ionic g provider HttpService ...

  10. XML读取信息并显示

    这个类命名叫Message.cs namespace Common { public class Message { /// <summary> /// 信息编号 /// </sum ...