默认情况当你执行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. Spring-mvc配置“/”路径过滤问题

    首先大家都知道"/*"可以匹配所有url,包括带扩展名的,一般只用在过滤器上. 一般Spring-mvc的核心 <servlet> <servlet-name&g ...

  2. Jquery Ajax type的4种类型

    Ajax type这个里面填什么呢?通常大家都会说get和post.那么还有2个是什么呢 $.ajax({ url: 'http://www.cnblogs.com/youku/', type: '' ...

  3. ArrayList 和 LinkedList 的实现与区别

    (转载请标明出处) 1.ArrayLis t的实现 2.LinkedLis t的实现 3.ArrayList 和 LinkedList 的区别 ArrayList 的实现: 1.MyArrayList ...

  4. 为什么你需要将代码迁移到ASP.NET Core 2.0?

    随着 .NET Core 2.0 的发布,.NET 开源跨平台迎来了新的时代.开发者们可以选择使用命令行.个人喜好的文本编辑器.Visual Studio 2017 15.3 和 Visual Stu ...

  5. HiWord()

    #define HIWORD(I) ( ( WORD ) ( ( ( DWORD )( I ) >> 16) & 0xFFFF ) ). 这个宏传回一个WORD值(16位的无符号整 ...

  6. .h(头文件) .lib(库文件) .dll(动态链接库文件) 之间的关系和作用的区分

    .h头文件是编译时必须的,lib是链接时需要的,dll是运行时需要的.附加依赖项的是.lib不是.dll,若生成了DLL,则肯定也生成 LIB文件.如果要完成源代码的编译和链接,有头文件和lib就够了 ...

  7. Linux Bash Shell字符串截取

    #!/bin/bash#定义变量赋值时等号两边不能有空格,否则会报命令不存在  # 运行shell脚本两种方式 # 1.作为解释参数 /bin/sh test.sh ;  2.作为可执行文件 chmo ...

  8. 基于搜狗搜索的微信公众号爬虫实现(C#版本)

    Author: Hoyho Luo Email: luohaihao@gmail.com Source Url:http://here2say.me/11/ 转载请保留此出处 本文介绍基于搜狗的微信公 ...

  9. 配置zabbix agent向多个server发送数据

    1.背景: agent 端:dba-test-hzj02  172.16.59.197 server端:172.16.59.197  ,172.16.59.98 2.方式: 配置多个server,se ...

  10. 编写 WPF DataGrid 列模板,实现更好的用户体验

    Julie Lerman 下载代码示例 最近我在为一个客户做一些 Windows Presentation Foundation (WPF) 方面的工作. 虽然我提倡使用第三方工具,但有时也会避免使用 ...