• NopCommerce添加事务机制


    NopCommerce现在最新版是3.9,不过依然没有事务机制。作为一个商城,我觉得事务也还是很有必要的。以下事务代码以3.9版本作为参考:

    首先,IDbContext接口继承IDisposable接口,以便手动释放相关资源,并添加一个新方法CurrentEntries,目的是得到跟踪实体的当前跟踪状态(主要作用是使用事务回滚后改变当前实体对应的状态):

            /// <summary>
            /// 得到跟踪实体的当前跟踪状态
            /// </summary>
            /// <returns></returns>
            IEnumerable<DbEntityEntry> CurrentEntries();

    自然相应的IDbContext接口实现类NopObjectContext也要实现该方法:

            public IEnumerable<DbEntityEntry> CurrentEntries()
            {
                return ChangeTracker.Entries();
            }

    注意:主项目代码添加这个方法之后,所有需要操作数据库的插件都要实现该方法,这个大家自行斟酌,如果插件也需要事务的话。

    添加一个接口命名IUnitOfWork,如下:

        public interface IUnitOfWork : IDisposable
        {
            /// <summary>
            /// 开启事务
            /// </summary>
            /// <param name="isolationLevel"></param>
            void BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.Unspecified);
    
            /// <summary>
            /// 提交
            /// </summary>
            void Commit();
    
            /// <summary>
            /// 回滚
            /// </summary>
            void Rollback();
    
            /// <summary>
            /// 释放资源
            /// </summary>
            /// <param name="disposing">是否释放</param>
            void Dispose(bool disposing);
        }

    并实现该接口,添加实现类命名UnitOfWork,如下:

        public class UnitOfWork : IUnitOfWork
        {
            private IDbContext _context;
            private ObjectContext _objectContext;
            private IDbTransaction _transaction;
    
            private bool _disposed;
    
            public UnitOfWork(IDbContext context)
            {
                _context = context;
            }
    
            public void BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.Unspecified)
            {
                _objectContext = ((IObjectContextAdapter)_context).ObjectContext;
                if (_objectContext.Connection.State != ConnectionState.Open)
                    _objectContext.Connection.Open();
    
                _transaction = _objectContext.Connection.BeginTransaction(isolationLevel);
            }
    
            public void Commit()
            {
                _transaction.Commit();
            }
    
            public void Rollback()
            {
                _transaction.Rollback();
                foreach (var entry in _context.CurrentEntries())
                {
                    switch (entry.State)
                    {
                        case EntityState.Modified:
                            entry.State = EntityState.Unchanged;
                            break;
                        case EntityState.Added:
                            entry.State = EntityState.Detached;
                            break;
                        case EntityState.Deleted:
                            entry.State = EntityState.Unchanged;
                            break;
                    }
                }
            }
    
            public void Dispose(bool disposing)
            {
                if (_disposed)
                    return;
    
                if (disposing)
                {
                    try
                    {
                        if (_objectContext != null && _objectContext.Connection.State == ConnectionState.Open)
                            _objectContext.Connection.Close();
                    }
                    catch (ObjectDisposedException)
                    {
                    }
                    if (_context != null)
                    {
                        _context.Dispose();
                        _context = null;
                    }
                }
    
                _disposed = true;
            }
    
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
        }

    代码很好理解,我就不多做注释了,不清楚的自行网上了解。

    下面附上我写的单元测试:

        [TestClass]
        public class UnitTest1
        {
            protected static NopObjectContext Context = new NopObjectContext(ConfigurationManager.ConnectionStrings["ConnectionStr"].ToString());
            private readonly IUnitOfWork _unitOfWork = new UnitOfWork(Context);
            protected readonly IRepository<ForumGroup> ForumGroupRepository = new EfRepository<ForumGroup>(Context);
            protected readonly IRepository<Setting> SettingRepository = new EfRepository<Setting>(Context);
    
            [TestMethod]
            public void Can_Commit_Test()
            {
                try
                {
                    _unitOfWork.BeginTransaction(); // 开启事务
    
                    var forumGroup = new ForumGroup
                    {
                        Name = "ForumGroup1", // 自行建立Name的唯一约束测试,测试两次第二次会自行回滚
                        DisplayOrder = 1,
                        CreatedOnUtc = DateTime.Now,
                        UpdatedOnUtc = DateTime.Now.AddDays(1)
                    };
                    ForumGroupRepository.Insert(forumGroup); // 第一次插入数据
    
                    var setting = new Setting
                    {
                        Name = "test_transaction_name",
                        Value = "test_transaction_value",
                        StoreId = 1
                    };
                    SettingRepository.Insert(setting);
    
                    _unitOfWork.Commit(); // 提交
                }
                catch (Exception)
                {
                    _unitOfWork.Rollback(); // 回滚
                }
    
                Assert.AreEqual(ForumGroupRepository.TableNoTracking.Count(), 1);
    Assert.AreEqual(SettingRepository.TableNoTracking.Count(x => x.Name == "test_transaction_name"), 1); } }

     如果你觉得对你有帮助,右侧打个赏呗!

    Authori:黄仲秋

    QQ:875755898

  • 相关阅读:
    C# 打印文件
    oc语言学习之基础知识点介绍(五):OC进阶
    oc语言学习之基础知识点介绍(四):方法的重写、多态以及self、super的介绍
    oc语言学习之基础知识点介绍(三):类方法、封装以及继承的介绍
    oc语言学习之基础知识点介绍(二):类和对象的进一步介绍
    oc语言学习之基础知识点介绍(一):OC介绍
    c语言学习之基础知识点介绍(二十):预处理指令
    c语言学习之基础知识点介绍(十九):内存操作函数
    XCTF-ics-04
    Portswigger-web-security-academy:dom-base_xss
  • 原文地址:https://www.cnblogs.com/YUTOUYUWEI/p/7589119.html
Copyright © 2020-2023  润新知