本文转自:http://www.binaryintellect.net/articles/165bb877-27ee-4efa-9fa3-40cd0cf69e49.aspx

When you make any additions, modifications and deletions to an Entity  Framework DbSet and call SaveChanges(), EF starts a new transaction and executes  all the INSERT, UPDATE and DELETE operations inside that newly created  transaction. If the call to SaveChanges() succeeds the underlying transaction is  committed, otherwise the transaction is rolled back. In some cases you may want  that multiple calls to SaveChanges() be executed in the same transaction.  Luckily, Entity Framework 6 provides an easy way to accomplish the same.

Let's assume that you have an Entity Framework data model with Customer  entity as shown below:

Now suppose that you wrote the following code to add two Customer records to  the database.

  1. NorthwindEntities db = new NorthwindEntities();
  2.  
  3. Customer obj1 = new Customer();
  4. obj1.CustomerID = "ABCDE";
  5. obj1.CompanyName = "Company 1";
  6. obj1.ContactName = "Contact 1";
  7. obj1.Country = "USA";
  8. db.Customers.Add(obj1);
  9.  
  10. db.SaveChanges();

  11. Customer obj2 = new Customer();
  12. obj2.CustomerID = "PQRST";
  13. obj2.CompanyName = "Company 2";
  14. obj2.ContactName = "Contact 2";
  15. obj2.Country = "USA";
  16. db.Customers.Add(obj2);
  17.  
  18. db.SaveChanges();

In this case two calls to SaveChanges() are made. The first call adds the  first Customer to the database and the second call adds the other Customer to  the database. If the second call to SaveChanges() fails for some reason the  first Customer still gets added to the database because each call to SaveChanges()  runs in its own transaction.

Now let's modify this code as shown below:

  1. using(NorthwindEntities db = new NorthwindEntities())
  2. {
  3. DbContextTransaction transaction = db.Database.BeginTransaction();

  4. try
  5. {
  6. //insert a record
  7. Customer obj1 = new Customer();
  8. obj1.CustomerID = "ABCDE";
  9. obj1.CompanyName = "Company 1";
  10. obj1.ContactName = "Contact 1";
  11. obj1.Country = "USA";
  12. db.Customers.Add(obj1);
  13.  
  14. //first call to SaveChanges()
  15.  
  16. db.SaveChanges();

  17. //insert another record
  18. Customer obj2 = new Customer();
  19. obj2.CustomerID = "PQRST";
  20. obj2.CompanyName = "Company 2";
  21. obj2.ContactName = "Contact 2";
  22. obj2.Country = "USA";
  23. db.Customers.Add(obj2);
  24.  
  25. //second call to SaveChanges()
  26.  
  27. db.SaveChanges();

  28. transaction.Commit();
  29. }
  30. catch
  31. {
  32. transaction.Rollback();
  33. }
  34. }

Notice that the above code explicitly starts a transaction by calling  BeginTransaction() method on the Database property of the data context. The  BeginTransaction() returns a DbContextTransaction object which is stored in a  local variable. This object is used to either commit or rollback the transaction  later in the code.

The code then adds Customer entities as before and calls SaveChanges() after  each addition. This time since our code is explicitly creating a transaction,  both the calls to SaveChanges() are treated as the part of this transaction. If  both the calls to SaveChanges() are successful we call Commit() method of  DbContextTransaction object. If any of them fails we call the Rollback() method  of DbContextTransaction object.

You can test the above code by setting the CustomerID of the second Customer  to a string longer than five characters.

Note: There is also UseTransaction() method that can be used if you wish to couple EF  operations with plain ADO.NET transactions.

That's it for now! Keep coding !!

Bipin Joshi is a software consultant, trainer, author and a yogi having 21+ years of experience in software development. He conducts online courses in ASP.NET MVC / Core, jQuery, AngularJS, and Design Patterns. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced Yoga way of life he also teaches Ajapa Meditation to interested individuals. To know more about him click here.

[转]Wrapping multiple calls to SaveChanges() in a single transaction的更多相关文章

  1. Enlisting multiple 1-phase aware participants in the same transaction

    In some cases it may be necessary to enlist participants that aren't two-phase commit aware into a t ...

  2. 从文件中读取字符-多次调用read characters from file multiple calls

    [抄题]: 接口:int read4(char * buf)一次从文件中读取 4 个字符.返回值是实际读取的字符数. 例如,如果文件中只剩下 3 个字符,则返回 3.通过使用read4 接口,实现从文 ...

  3. Oracle Applications Multiple Organizations Access Control for Custom Code

    档 ID 420787.1 White Paper Oracle Applications Multiple Organizations Access Control for Custom Code ...

  4. Entity Framework中DbContext结合TransactionScope提交事务的正确方式

    问: I would like know what is the best possible way to implement transactions with DBContext. In part ...

  5. postgresql大批量数据导入方法

    一直没有好好关注这个功能,昨天看了一下,数据库插入有瓶颈,今天研究了一下: 主要有以下方案: 1.使用copy从文件导入: copy table_001(a, b, "f", d, ...

  6. XA Transactions Restrictions on XA Transactions

    小结: 1.innodb支持XA事务: 2.XA协议作为资源管理器(数据库)与事务管理器的接口标准: 3.提交或者回滚的点:必须所有的组件被提交或者被回滚: 4.2阶段 PC-1,TM告知所有RM要准 ...

  7. Wrapping calls to the Rational Functional Tester API——调用Rational Functional Tester封装的API

    转自:http://www.ibm.com/developerworks/lotus/library/rft-api/index.html The Rational GUI automation to ...

  8. WCF Concurrency (Single, Multiple, and Reentrant) and Throttling

    http://www.codeproject.com/Articles/89858/WCF-Concurrency-Single-Multiple-and-Reentrant-and Introduc ...

  9. Learning WCF Chapter1 Exposing Multiple Service Endpoints

    So far in this chapter,I have shown you different ways to create services,how to expose a service en ...

随机推荐

  1. VSCODE 针对调试C语言时一闪而过解决办法

    针对调试C语言时一闪而过解决办法 前提: 已经按照 C/C++ 已经安装 MINGW(并配置完成) 原因:  主要是因为tasks的配置没有写对 解决办法: tasks.json { // See h ...

  2. zookeeper安装和使用 windows

    的 Zookeeper 是以 3.4.5 这个稳定版本为基础,最新的版本可以通过官网 http://hadoop.apache.org/zookeeper/来获取,Zookeeper 的安装非常简单, ...

  3. mybatis 学习笔记(四):mybatis 和 spring 的整合

    mybatis 学习笔记(四):mybatis 和 spring 的整合 尝试一下整合 mybatis 和 spring. 思路 spring通过单例方式管理SqlSessionFactory. sp ...

  4. 题解 P1614 【爱与愁的心痛】

    题目链接 前缀和. #重点在一个小小的常数优化 但是数据大了以后比楼下们跑的会快!!! 楼下用前缀和的题解都是跑了两遍循环. 而实际上一遍循环就可以呀. 就是加一段这个 if(i>=m) if( ...

  5. Ajaxa的原生使用方法

    Ajax整合了JavaScript.xml.CSS等现有技术而成,全称为Asynchronous JavaScript And XML,即异步的 JavaScript和xml.它使用了JavaScri ...

  6. js Array属性和用法

    //构造函数创建数组 var arr1=new Array(); //字面量的方式 var arr2=[]; 1.Array.isArray(对象)---->判断这个对象是不是数组 //判断对象 ...

  7. Qt 学习之路 2(37):文本文件读写

    Qt 学习之路 2(37):文本文件读写 豆子 2013年1月7日 Qt 学习之路 2 23条评论 上一章我们介绍了有关二进制文件的读写.二进制文件比较小巧,却不是人可读的格式.而文本文件是一种人可读 ...

  8. npm i -S -D -g 区别

    npm install 本身就有一个别名 npm i npm i module_name -S    即    npm install module_name --save     写入depende ...

  9. MySql 碎片

    查看某个表所占空间,以及碎片大小. select table_name,engine,table_rows,data_length+index_length length,DATA_FREE from ...

  10. C++_异常7-exception类

    C++异常的主要目的是为了设计容错程序提供语言级支持. 即异常使得在程序设计中包含错误处理功能更加容易,以免事后采取一些严格的错误处理方式. 异常的灵活性和相对方便性激励着程序员在条件允许的情况下在程 ...