EntityFramework 事务处理
默认情况下,当EF调用SaveChanges()时,会把生成的所有SQL命令“包”到一个“事务(transaction)”中,只要有一个数据更新操作失败,整个事务将回滚。
在多数情况下,如果你总在数据更新操作代码中使用一个而不是多个DbContext对象,并且只是在最后调用一次SaveChanges(),那么EF的默认事务处理机制己经够用了,无需做额外的事情。
然而,如果出现以下的情形,你就必须显式地处理事务了。
第一种情况:你需要分阶段地保存数据,因而需要多次调用SaveChanges()或者执行修改数据库的SQL命令。
请看以下示例代码:
using (var context = new MyDbContext())
{
try
{
Person3 p = context.People3.First();
p.Name ="newName" + (new Random().Next(, ));
context.SaveChanges();
context.Database.ExecuteSqlCommand("update Person3 setDescription={0} where Person3Id={1}",
"DescriptionModified at " + DateTime.Now.ToShortTimeString(),
p.Person3Id);
p.age *= ;
context.SaveChanges();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
上述代码中,调用两次SaveChanges(),还有一次执行Update命令。
如果在最后一次SaveChanges()中出现异常,虽然最后一次没成功,但你会发现前两次数据己经保存!这就带来了数据不一致的问题。
对于这种场景,你需要显式地编写事务代码了(注:以下代码适用于EF6):
using (var context = new MyDbContext())
{
using (var transaction =context.Database.BeginTransaction())
{
try
{
…… context.SaveChanges(); context.Database.ExecuteSqlCommand("……); …… context.SaveChanges();
transaction.Commit(); }
catch (Exception e)
{
Console.WriteLine(e.Message);
transaction.Rollback();
}
}
}
特别要注意一定要调用commit(),我测试发现,只要不Commit,即使没有异常发生,事务仍将回滚,数据库中的数据不会更新。
第2种情况,你需要使用多个DbContext保存数据。
以下是处理这种场景的典型代码:
static void TestTransactionScope2()
{
using (TransactionScope scope = new TransactionScope())
{
String connStr = ……;
using (var conn = newSqlConnection(connStr))
{
try
{
conn.Open();
using (var context1 =new MyDbContext(conn, contextOwnsConnection: false))
{
……
context1.SaveChanges();
}
using (var context2 =new MyDbContext(conn, contextOwnsConnection: false))
{
context2.Database.ExecuteSqlCommand(……);
context2.SaveChanges();
}
using (var context3 =new MyDbContext2(conn, contextOwnsConnection: false))
{
……
context3.SaveChanges();
}
scope.Complete();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
conn.Close();
}
}
}
}
上述代码中有几个关键点:
(1)在构造DbContext对象时,需要把一个己打开的数据库连接对象传给它,并且需要指定EF在DbContext对象销毁时不关闭数据库连接。
为实现此目的,你的DbContext对象应该类似于是这样的,提供两个重载的构造函数:
public class MyDbContext2 : DbContext
{ public MyDbContext2(DbConnection conn, boolcontextOwnsConnection):base(conn,contextOwnsConnection)
{ } public MyDbContext2():base()
{ }
public DbSet<OtherEntity> OtherEntities { get; set; } ……
}
注意在代码结束时关闭连接。
(2)如果不Commit,则所有数据将不会保存。
(3)你的计算机需要启动MSDTC(分布式交易协调器),请先在控制面板中打开Distributed Transaction Coordinator服务,否则上述代码将在运行时抛出MSDTC服务不可用的异常。
很明显,当事务需要使用多个不同类型的DbContext对象时,Windows需要启动MSDTC,这会对性能有所影响,因此在开发中应该尽量避免这种情况,如无必要,不要在单个事务中使用多个不同种类的DbContext对象。
转自:http://blog.csdn.net/bitfan/article/details/14231561
EntityFramework 事务处理的更多相关文章
- EntityFramework用法探索(八)事务处理
使用 前文中描述的Retail示例 ,在Customer对象的Mapping中设置Name属性:我们构造一个有效的Customer对象,再构造一个无效的Name属性为空的对象. DomainModel ...
- (转)EntityFramework之领域驱动设计实践
EntityFramework之领域驱动设计实践 - 前言 EntityFramework之领域驱动设计实践 (一):从DataTable到EntityObject EntityFramework之领 ...
- .net EntityFramework用法探索系列 1
EntityFramework用法探索系列 (一)DatabaseFirst (二)CodeFirst (三)CodeFirst流畅API (四)Repository和UnitOfWork (五)引入 ...
- EntityFramework 6.x多个上下文迁移实现分布式事务
前言 自从项目上了.NET Core平台用上了EntityFramework Core就再没碰过EntityFramework 6.x版本,目前而言EntityFramework 6.x是用的最多,无 ...
- ASP.NET没有魔法——ASP.NET MVC 与数据库之EntityFramework配置与连接字符串
前几篇文章中介绍了如何使用Entity Framework来操作数据库,但是对EF的配置.连接字符串的指定仍然存在一些疑问. 本章将对EF的配置进行介绍. EF可以通过两种方式来实现配置,分别是代码方 ...
- EntityFramework之领域驱动设计实践
EntityFramework之领域驱动设计实践 - 前言 EntityFramework之领域驱动设计实践 (一):从DataTable到EntityObject EntityFramework之领 ...
- 基于 EntityFramework 的数据库主从读写分离架构(2)- 改进配置和添加事务支持
回到目录,完整代码请查看(https://github.com/cjw0511/NDF.Infrastructure)中的目录: src\ NDF.Data.EntityFramew ...
- C# 嵌入dll 动软代码生成器基础使用 系统缓存全解析 .NET开发中的事务处理大比拼 C#之数据类型学习 【基于EF Core的Code First模式的DotNetCore快速开发框架】完成对DB First代码生成的支持 基于EF Core的Code First模式的DotNetCore快速开发框架 【懒人有道】在asp.net core中实现程序集注入
C# 嵌入dll 在很多时候我们在生成C#exe文件时,如果在工程里调用了dll文件时,那么如果不加以处理的话在生成的exe文件运行时需要连同这个dll一起转移,相比于一个单独干净的exe,这种形 ...
- ASP.NET开发实战——(十一)ASP.NET MVC 与数据库之EntityFramework配置与连接字符串
前几篇文章中介绍了如何使用Entity Framework来操作数据库,但是对EF的配置.连接字符串的指定仍然存在一些疑问,EF可以通过两种方式来实现配置,分别是代码方式和配置文件. 本章将通过以下几 ...
随机推荐
- 11、Struts2 的文件上传和下载
文件上传 表单准备 要想使用 HTML 表单上传一个或多个文件 须把 HTML 表单的 enctype 属性设置为 multipart/form-data 须把 HTML 表单的method 属性设置 ...
- [C#] 简单的 Helper 封装 -- CookieHelper
using System; using System.Web; namespace ConsoleApplication5 { /// <summary> /// Cookie 助手 // ...
- Xamarin与Visual stuido2015离线安装包分享
最近看见大伙留言才知道国内安装Xamarin开发原来这么艰辛啊! 第一:网速不快 第二:Android SDK下载受限 等等... 鉴于这些原因,特写下这篇文章以及分享打包好的离线包以帮助大家尽快体验 ...
- Xamarin+Prism小试牛刀:定制跨平台Outlook邮箱应用
通过本文你将学会如下内容: 1,如何使用Xamarin开发跨平台(Windows,Android,iOS)应用. 2,如何使用微软的登录界面登入Microsoft账号. 3,如何使用Outlook邮箱 ...
- 对Thoughtworks的有趣笔试题实践
记得2014年在网上看到Thoughtworks的一道笔试题,当时觉得挺有意思,但是没动手去写.这几天又在网上看到了,于是我抽了一点时间写了下,我把程序运行的结果跟网上的答案对了一下,应该是对的,但是 ...
- C#中如何在Excel工作表创建混合型图表
在进行图表分析的时候,我们可能需要在一张图表呈现两个或多个样式的图表,以便更加清晰.直观地查看不同的数据大小和变化趋势.在这篇文章中,我将分享C#中如何在一张图表中创建不同的图表类型,其中包括如何在同 ...
- beans.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- Open-Test 测试驱动模式与版本号管理机制
以测试用例驱动项目开发,coding/case俩条线并走模式. 1.开发人员只负责功能实现: 2.测试人员提供自测用例,研发人员jenkins持续集成项目后自动化执行自测用例,通过后方可转测试 ...
- mysql数据库主从同步
环境: Mater: CentOS7.1 5.5.52-MariaDB 192.168.108.133 Slave: CentOS7.1 5.5.52-MariaDB 192.168. ...
- Vue.js——vue-resource全攻略
概述 上一篇我们介绍了如何将$.ajax和Vue.js结合在一起使用,并实现了一个简单的跨域CURD示例.Vue.js是数据驱动的,这使得我们并不需要直接操作DOM,如果我们不需要使用jQuery的D ...