




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、EntityFramework 与 TransactionScope 事务和并发控制EntityFramework 与 TransactionScope 事务和并发控制 最近在园子里看到一篇关于 TransactionScope 的文章,发现 事务和并发控制是新接触 Entity Framework 和 Transaction Scope的园友们不易理解的问题,遂组织此文跟大家共同探 讨。首先事务的 ACID 特性作为最基础的知识我想大家都应该知 道了。 ADO.NET 的 SQLTransaction 就是 .NET 框架下访问 SqlServer 时最底层的数据库事务对象, 它可以用来将多
2、次的 数据库访问封装为“原子操作” ,也可以通过修改隔离级别 来控制并发时的行为。 TransactionScope 则是为了在分布式数 据节点上完成事务的工具,它经常被用在业务逻辑层将多个 数据库操作组织成业务事务的场景,可以做到透明的可分布 式事务控制和隐式失败回滚。但与此同时也经常有人提到 TransactionScope 有性能和部署方面的问题, 关于这一点, 根 据 MSDN 的 Using the TransactionScope Class 的说法,当一 个 TransactionScope 包含的操作是同一个数据库连接时,它 的行为与 SqlTransaction 是类似的。当
3、它在多个数据库连接 上进行数据操作时,则会将本地数据库事务提升为分布式事 务,而这种提升要求各个节点均安装并启动 DTC 服务来支 持分布式事务的协调工作,它的性能与本地数据库事务相比 会低很多,这也是 CAP 定律说的分布式系统的 Consistency 和 Availability 不可兼得的典型例子。 所以当我们选择是否使 用 TransactionScope 时,一定要确认它会不会导致不想发生 的分布式事务,也应该确保事务尽快做完它该做的事情,为 了确认事务是否被提升我们可以用 SQL Profiler 去跟踪相关 的事件。然后再来看一看 Entity Framework ,其实 EF
4、 也跟事务有关系。 它的 Context 概念来源于 Unit of Work 模式, Context 记录提 交前的所有 Entity 变化,并在 SaveChanges 方法调用时发起 真正的数据库操作, SaveChanges 方法在默认情况下隐含一 个事务,并且试图使用乐观并发控制来提交数据,但是为了 进行并发控制我们需要将 Entity Property 的 ConcurrencyMode 设置为 Fixed 才行,否则 EF 不理会在此 Entity 上面发生的并发修改,这一点可以参考 MSDN Saving Changes and Managing Concurrency。微软推
5、荐大家使用以下 方法来捕获冲突的并发操作,并使用 RefreshMode 来选择覆 盖或丢弃失败的操作:1 try2 3 / Try to save changes, which may cause a conflict.10Console.WriteLine(No conflicts. +num.ToString() + updates saved.);catch (OptimisticConcurrencyException)/ Resolve the concurrency conflict byrefreshing the11/ object context before re-sav
6、ing changes.12context.Refresh(RefreshMode.ClientWins,orders);1314/ Save changes.15context.SaveChanges();1617Console.WriteLine(OptimisticConcurrencyException + handled and changes saved);18当然除了乐观并发控制我们还可以对冲突特别频繁、冲突解决代价很大的用例进行悲观并发控制。悲观并发基本思想是不让数据被同时离线修改,也就是像源码管理里面“加锁”功能一样,码农甲锁上了这个文件,乙就不能再修改了,这样一来这个文件就
7、不可能发生冲突,悲观并发控制实现的方 式比如数据行加 IsLocked 字段等。最后为了进行多 Context 事务,当然还可以混合使用TransactionScope 和 EF。 好了理论简单介绍完,下面的例子是几种不同的方法对并发 控制的效果,需求是每个 Member 都有个 HasMessage 字段, 初始为False,我们需要给其中一个Member加入唯一一条MemberMessage,并将 Member.HasMessage置为 True。 建库脚本:1 CREATE DATABASE TransactionTest2 GO34 USE TransactionTest5 GO67
8、CREATE TABLE dbo.Member(8 Id int IDENTITY(1,1) NOT NULL,9 Name nvarchar(32) NOT NULL,10 HasMessage bit NOT NULL,11 CONSTRAINT PK_Member PRIMARY KEY CLUSTERED12 (13 Id ASC14 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS= ON,ALLOW_PAGE_LOCKS = ON) ON PRIMA
9、RY15 ) ON PRIMARY16 GO17 SET IDENTITY_INSERT dbo.Member ON18 INSERT dbo.Member (Id, Name, HasMessage) VALUES (1, NTom, 0)19 INSERT dbo.Member (Id, Name, HasMessage) VALUES (2, NJerry, 0)20 SET IDENTITY_INSERT dbo.Member OFF2122 CREATE TABLE dbo.MemberMessage(23 Id int IDENTITY(1,1) NOT NULL,24 Messa
10、ge nvarchar(128) NOT NULL,25 MemberId int NOT NULL,26 CONSTRAINT PK_MemberMessage PRIMARY KEYCLUSTERED27 (28 Id ASC29 )WITH (PAD_INDEX = OFF,STATISTICS_NORECOMPUTE = OFF,IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON) ON PRIMARY30 ) ON PRIMARY31 GO3233 ALTER TABLE dbo.MemberMessage
11、 WITH CHECKADD CONSTRAINT FK_MemberMessage_Member FOREIGN KEY(MemberId)34 REFERENCES dbo.Member (Id)35 GO36 ALTER TABLE dbo.MemberMessage CHECKCONSTRAINT FK_MemberMessage_Member37 GOView Code方法1:不使用TransactionScope,只依赖Entity各字段的默 认并发控制。Context 和 Entity 定义1 public class MyDbContext : DbContext2 3 pub
12、lic MyDbContext() : base(TransactionTest) 45 public MyDbContext(string connectionString) :6 base(connectionString)7 89 1011 public DbSet<Member> Members get; set; 12 1314 Table(Member)15 public class Member16 17 Key18 public int Id get; set; 1920public string Name get; set; 2122public bool Has
13、Message get; set; 2324public virtual ICollection<MemberMessage>Messages get; set; 25 2627 Table(MemberMessage)28 public class MemberMessage29 30 Key31 public int Id get; set; 3233 public string Message get; set; 3435public int MemberId get; set; 3637 ForeignKey(MemberId)38 public virtual Membe
14、r Member get; set; 39 View Code测试代码1 try2 3 using (var context = new MyDbContext()4 5 var tom = context.Members.FirstOrDefault(m=> m.Id = 1);6 if (tom != null && !tom.HasMessage)7 8 Console.WriteLine(Press Enter to Insert MemberMessage.);9Console.ReadLine();10tom.Messages.Add(new MemberMe
15、ssage()1112MessageHi Tom!13);14tom.HasMessage = true;15context.SaveChanges();16Console.WriteLine(Insert Completed!);1719 20 catch (Exception ex)21 22 Console.WriteLine(Insert Failed: + ex);23 View Code 同时运行两个程序,结果是无法确保不重复插入通过分析不难发现,该场景的并发控制关键就在于插入前检查HasMessage如果是False,则插入 MemberMessage后更新 Member.Has
16、Message字段时需要再次检查数据库中HasMessage字段是否为False,如果为True就是有其他人并发的更改了该字段,本次保存应该回滚或做其他处理。所以 为此需要有针对性的加入并发控制。方法2:给HasMessage字段加上并发检查1 Table(Member)2 public class Member3 Keypublic string Name get; set; 10ConcurrencyCheckpublic bool HasMessage get; set; 1112public virtual ICollection<MemberMessage>Message
17、s get; set; 13 仍然使用方法 1 的测试代码,结果则是其中一次数据插入会 抛出 OptimisticConcurrencyException ,也就是说防止重复插 入数据的目的已经达到了。那回过头来看看是否可以使用 TransactionScope 对 EF 进行并 发控制,于是有方法 3:使用 TransactionScope 但不给 Entity 加入并发检查Context 和 Entity 的定义与方法 1 完全一致,测试代码为1 try2 3 using (var scope = newSystem.Transactions.TransactionScope()45usi
18、ng (var context = new MyDbContext()67var tom= context.Members.FirstOrDefault(m> m.Id = 1);8if (tom !=null&& !tom.HasMessage)9 10 Console.WriteLine(Press Enter to InsertMemberMessage.);11 Console.ReadLine();12 tom.Messages.Add(newMemberMessage()13 14Message = Hi Tom!15 );16tom.HasMessage = true;17context.SaveChanges();18 Console.WriteLine(Insert Completed!)
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 烘焙店投资加盟合同范本
- 混凝土配料劳务合同范本
- 消防检测合同的补充协议
- 洗车店急需转让合同范本
- 漂流项目运营协议书范本
- 煤气管道转让协议书模板
- 泉州串串香加盟合同范本
- 物业顾问合同协议书范本
- 砂滤池清洗回填合同范本
- 铺面场地出租协议书模板
- 2025江苏苏州昆山国创投资集团有限公司第一期招聘17人笔试参考题库附带答案详解版
- QGDW11970.1-2023输变电工程水土保持技术规程第1部分水土保持方案
- 2025年七一党课-作风建设永远在路上学习教育党课
- 2025年淮南新东辰控股集团有限责任公司招聘笔试参考题库附带答案详解
- GB/T 18290.3-2000无焊连接第3部分:可接触无焊绝缘位移连接一般要求、试验方法和使用导则
- 高血压疾病证明书
- 新高三暑假弯道超车2021年高二期末主题班会学校活动ppt
- 对肝癌肝切除术指证的新近认识课件讲义
- 质量过程报告记录汇总表-scr与ncr表格报检单
- 患者误吸风险评价表完整优秀版
- Q∕SY 1477-2012 定向钻穿越管道外涂层技术规范
评论
0/150
提交评论