EF事务嵌套
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了EF事务嵌套相关的知识,希望对你有一定的参考价值。
EF中采用的是数据上下文DbContext,当针对数据库的所有操作共用一个数据上下文的时候,会使用同一个连接对象,因此连接打开一次,最后Save的时候关闭连接,避免了频繁的创建连接对象打开关闭,这在一定程度上提升了性能。
对比传统的DbHelper做法,传统的DbHelper通常将线性单元方法进行了封装,每个方法都会创建一个连接对象、打开关闭,因为DbHelper不能采用一个公用的Connection对象,因为如果共用一个连接对象,那么所有的请求操作都会采用这一个连接对象,打开关闭,如果访问量大的时候,瓶颈可想而知。
DAL层都是封装的原子性操作,但是在业务层中,要调用不同的DAL层对象,同时进行多个原子操作。
EF在这一点做到了采用同一个数据上下文,采用同一个连接对象,采用同一个事务,提升了性能。
但是如果你的DbContext是线程级别的,并且事务方法又互相调用就存在了事务嵌套问题,因为嵌套的事务一旦提交就作废了,所以要保证必须是最后提交,如果嵌套事务异常也要在保证外层的回滚
最后采用了事务计数的思想
public class MyDbContext : DbContext, ITransaction { public MyDbContext(string connectionString) : base(connectionString) { // 是否启动延迟加载 Configuration.LazyLoadingEnabled = false; // 是否启动代理 Configuration.ProxyCreationEnabled = false; Configuration.AutoDetectChangesEnabled = false; Configuration.ValidateOnSaveEnabled = false; } public void BeginTransaction() { if (this.Database.CurrentTransaction == null) { this.Database.BeginTransaction(); } this.BeginCounter++; this.IsTransaction = true; } public int Commit() { this.BeginCounter--; int result = this.SaveChanges(); if (this.BeginCounter==0) { this.IsTransaction = false; DbContextTransaction transaction = this.Database.CurrentTransaction; if (transaction != null) { transaction.Commit(); transaction.Dispose(); result += 1; } } return result; } public void Rollback() { this.BeginCounter--; if (this.BeginCounter == 0) { this.IsTransaction = false; DbContextTransaction transaction = this.Database.CurrentTransaction; if (transaction != null) { transaction.Rollback(); transaction.Dispose(); } } else { //this.BeginCounter = 1; throw new Exception("嵌套内部事务异常"); } } private bool isTransaction = false; /// <summary> /// 事务性操作 /// </summary> public bool IsTransaction { get { return isTransaction; } set { this.isTransaction = value; } } private int beginCounter = 0; /// <summary> /// 事务计数器 /// </summary> public int BeginCounter { get { return beginCounter; } set { this.beginCounter = value; } } }
以上是关于EF事务嵌套的主要内容,如果未能解决你的问题,请参考以下文章