默认情况当你执行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. [js高手之路]Node.js+jade+express+mongodb+mongoose+promise实现todolist

    promise主要是用来解决异步回调问题,其实还有好几种比promise更好的方案,后面再说,这节,我们先用promise来改造下,我以前写的一篇文章[js高手之路]javascript腾讯面试题学习 ...

  2. struts1.3学习

    一.基本配置 参考博客 项目结构 web.xml <!-- struts配置 --> <servlet> <servlet-name>action</serv ...

  3. BZOJ2748_音量调节_KEY

    [HAOI2012]音量调节 Time Limit: 3 Sec Memory Limit: 128 MB Description 一个吉他手准备参加一场演出.他不喜欢在演出时始终使用同一个音量,所以 ...

  4. Angular4 后台管理系统搭建(9) - 用自定义angular指令,实现在服务端验证

    最近这段时间发现,北京这用angular4 或 angular2的公司很少.几乎是没有.很担心自己是不是把精力放到了不应该的地方.白耽误了时间.但是随着我对新版angular框架理解的加深.个人感觉a ...

  5. 【转载】关于api-ms-win-crt-runtimel1-1-0.dll缺失的解决方案

    关于api-ms-win-crt-runtimel1-1-0.dll缺失的解决方案 目录 关于api-ms-win-crt-runtimel1-1-0dll缺失的解决方案 目录 安装VC redite ...

  6. SSM之整合Redis

    Redis安装与使用 第一步当然是安装Redis,这里以Windows上的安装为例. 首先下载Redis,可以选择msi或zip包安装方式 zip方式需打开cmd窗口,在解压后的目录下运行redis- ...

  7. hdu3018欧拉回路题

    Ant Trip Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S ...

  8. 1007 正整数分组 1010 只包含因子2 3 5的数 1014 X^2 Mod P 1024 矩阵中不重复的元素 1031 骨牌覆盖

    1007 正整数分组 将一堆正整数分为2组,要求2组的和相差最小. 例如:1 2 3 4 5,将1 2 4分为1组,3 5分为1组,两组和相差1,是所有方案中相差最少的.   Input 第1行:一个 ...

  9. jvm内存模型的理解

    今天周六,又开始啃一遍<深入理解java虚拟机>每次读的感觉不一样,大学代码量较少,读起来也就死记硬背. 1.堆:长度可变,运行时使用的变量:存放对象(new )和数组之类: 2.栈:长度 ...

  10. 用html +js+css 实现页面轮播图效果

    html 页面 <html lang="en"> <head> <meta charset="UTF-8"> <met ...