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事务嵌套的主要内容,如果未能解决你的问题,请参考以下文章

使用嵌套片段和动画对象

将片段添加到片段中(嵌套片段)

EF添加关联的提示问题:映射从第 260 行开始的片段时有问题:

Android 动画嵌套片段

片段事务中的实例化错误

EF6 自定义迁移表名