mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-11-04 09:15:27 +08:00 
			
		
		
		
	initial commit
This commit is contained in:
		
							
								
								
									
										41
									
								
								FreeSql.DbContext/UnitOfWork/IUnitOfWork.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								FreeSql.DbContext/UnitOfWork/IUnitOfWork.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Data;
 | 
			
		||||
using System.Data.Common;
 | 
			
		||||
 | 
			
		||||
namespace FreeSql
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 工作单元
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public interface IUnitOfWork : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 该对象 Select/Delete/Insert/Update/InsertOrUpdate 与工作单元事务保持一致,可省略传递 WithTransaction
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        IFreeSql Orm { get; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 开启事务,或者返回已开启的事务
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="isCreate">若未开启事务,则开启</param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        DbTransaction GetOrBeginTransaction(bool isCreate = true);
 | 
			
		||||
 | 
			
		||||
        IsolationLevel? IsolationLevel { get; set; }
 | 
			
		||||
 | 
			
		||||
        void Commit();
 | 
			
		||||
 | 
			
		||||
        void Rollback();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 工作单元内的实体变化跟踪
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        DbContext.EntityChangeReport EntityChangeReport { get; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 用户自定义的状态数据,便于扩展
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        Dictionary<string, object> States { get; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										185
									
								
								FreeSql.DbContext/UnitOfWork/UnitOfWork.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								FreeSql.DbContext/UnitOfWork/UnitOfWork.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,185 @@
 | 
			
		||||
using FreeSql.Internal.ObjectPool;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Data;
 | 
			
		||||
using System.Data.Common;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
 | 
			
		||||
namespace FreeSql
 | 
			
		||||
{
 | 
			
		||||
    public class UnitOfWork : IUnitOfWork
 | 
			
		||||
    {
 | 
			
		||||
        static int _seed;
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 正在使用中的工作单元(调试)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static ConcurrentDictionary<string, UnitOfWork> DebugBeingUsed { get; } = new ConcurrentDictionary<string, UnitOfWork>();
 | 
			
		||||
 | 
			
		||||
        protected IFreeSql _fsql;
 | 
			
		||||
        protected Object<DbConnection> _conn;
 | 
			
		||||
        protected DbTransaction _tran;
 | 
			
		||||
        protected Aop.TraceBeforeEventArgs _tranBefore;
 | 
			
		||||
        protected Aop.TraceBeforeEventArgs _uowBefore;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 开启事务后有值,是 UnitOfWork 的唯一标识<para></para>
 | 
			
		||||
        /// 格式:yyyyMMdd_HHmmss_种子id<para></para>
 | 
			
		||||
        /// 例如:20191121_214504_1
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string Id { get; private set; }
 | 
			
		||||
 | 
			
		||||
        public UnitOfWork(IFreeSql fsql)
 | 
			
		||||
        {
 | 
			
		||||
            _fsql = fsql;
 | 
			
		||||
            if (_fsql == null) throw new ArgumentNullException(nameof(fsql));
 | 
			
		||||
 | 
			
		||||
            _uowBefore = new Aop.TraceBeforeEventArgs("UnitOfWork", null);
 | 
			
		||||
            _fsql.Aop.TraceBeforeHandler?.Invoke(this, _uowBefore);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void ReturnObject()
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrEmpty(this.Id) == false && DebugBeingUsed.TryRemove(this.Id, out var old))
 | 
			
		||||
                this.Id = null;
 | 
			
		||||
 | 
			
		||||
            _fsql.Ado.MasterPool.Return(_conn);
 | 
			
		||||
            _tran = null;
 | 
			
		||||
            _conn = null;
 | 
			
		||||
            EntityChangeReport?.Report.Clear();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool Enable { get; private set; } = true;
 | 
			
		||||
 | 
			
		||||
        public void Close()
 | 
			
		||||
        {
 | 
			
		||||
            if (_tran != null)
 | 
			
		||||
                throw new Exception(DbContextStrings.TransactionHasBeenStarted);
 | 
			
		||||
 | 
			
		||||
            Enable = false;
 | 
			
		||||
        }
 | 
			
		||||
        public void Open()
 | 
			
		||||
        {
 | 
			
		||||
            Enable = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        DbContextScopedFreeSql _ormScoped;
 | 
			
		||||
        public IFreeSql Orm => _ormScoped ?? (_ormScoped = DbContextScopedFreeSql.Create(_fsql, null, () => this));
 | 
			
		||||
 | 
			
		||||
        public IsolationLevel? IsolationLevel { get; set; }
 | 
			
		||||
 | 
			
		||||
        public DbTransaction GetOrBeginTransaction(bool isCreate = true)
 | 
			
		||||
        {
 | 
			
		||||
            if (_tran != null) return _tran;
 | 
			
		||||
            if (isCreate == false) return null;
 | 
			
		||||
            if (!Enable) return null;
 | 
			
		||||
            if (_conn != null) _fsql.Ado.MasterPool.Return(_conn);
 | 
			
		||||
 | 
			
		||||
            _tranBefore = new Aop.TraceBeforeEventArgs("BeginTransaction", IsolationLevel);
 | 
			
		||||
            _fsql?.Aop.TraceBeforeHandler?.Invoke(this, _tranBefore);
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                _conn = _fsql.Ado.MasterPool.Get();
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    _tran = IsolationLevel == null ?
 | 
			
		||||
                        _conn.Value.BeginTransaction() :
 | 
			
		||||
                        _conn.Value.BeginTransaction(IsolationLevel.Value);
 | 
			
		||||
 | 
			
		||||
                    this.Id = $"{DateTime.Now.ToString("yyyyMMdd_HHmmss")}_{Interlocked.Increment(ref _seed)}";
 | 
			
		||||
                    DebugBeingUsed.TryAdd(this.Id, this);
 | 
			
		||||
                }
 | 
			
		||||
                catch
 | 
			
		||||
                {
 | 
			
		||||
                    ReturnObject();
 | 
			
		||||
                    throw;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                _fsql?.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(_tranBefore, "失败", ex));
 | 
			
		||||
#pragma warning disable CA2200 // 再次引发以保留堆栈详细信息
 | 
			
		||||
                throw ex;
 | 
			
		||||
#pragma warning restore CA2200 // 再次引发以保留堆栈详细信息
 | 
			
		||||
            }
 | 
			
		||||
            return _tran;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Commit()
 | 
			
		||||
        {
 | 
			
		||||
            var isCommited = false;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (_tran != null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (_tran.Connection != null) _tran.Commit();
 | 
			
		||||
                    isCommited = true;
 | 
			
		||||
                    _fsql?.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(_tranBefore, "提交", null));
 | 
			
		||||
 | 
			
		||||
                    if (EntityChangeReport != null && EntityChangeReport.OnChange != null && EntityChangeReport.Report.Any() == true)
 | 
			
		||||
                        EntityChangeReport.OnChange.Invoke(EntityChangeReport.Report);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                if (isCommited == false)
 | 
			
		||||
                    _fsql?.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(_tranBefore, "提交失败", ex));
 | 
			
		||||
#pragma warning disable CA2200 // 再次引发以保留堆栈详细信息
 | 
			
		||||
                throw ex;
 | 
			
		||||
#pragma warning restore CA2200 // 再次引发以保留堆栈详细信息
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                ReturnObject();
 | 
			
		||||
                _tranBefore = null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public void Rollback()
 | 
			
		||||
        {
 | 
			
		||||
            var isRollbacked = false;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (_tran != null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (_tran.Connection != null) _tran.Rollback();
 | 
			
		||||
                    isRollbacked = true;
 | 
			
		||||
                    _fsql?.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(_tranBefore, "回滚", null));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                if (isRollbacked == false)
 | 
			
		||||
                    _fsql?.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(_tranBefore, "回滚失败", ex));
 | 
			
		||||
#pragma warning disable CA2200 // 再次引发以保留堆栈详细信息
 | 
			
		||||
                throw ex;
 | 
			
		||||
#pragma warning restore CA2200 // 再次引发以保留堆栈详细信息
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                ReturnObject();
 | 
			
		||||
                _tranBefore = null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public DbContext.EntityChangeReport EntityChangeReport { get; } = new DbContext.EntityChangeReport();
 | 
			
		||||
 | 
			
		||||
        public Dictionary<string, object> States { get; } = new Dictionary<string, object>();
 | 
			
		||||
 | 
			
		||||
        ~UnitOfWork() => this.Dispose();
 | 
			
		||||
        int _disposeCounter;
 | 
			
		||||
        public void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            if (Interlocked.Increment(ref _disposeCounter) != 1) return;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                this.Rollback();
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                _fsql?.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(_uowBefore, "释放", null));
 | 
			
		||||
                GC.SuppressFinalize(this);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										270
									
								
								FreeSql.DbContext/UnitOfWork/UnitOfWorkManager.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										270
									
								
								FreeSql.DbContext/UnitOfWork/UnitOfWorkManager.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,270 @@
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Data;
 | 
			
		||||
using System.Data.Common;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
 | 
			
		||||
namespace FreeSql
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 工作单元管理器
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class UnitOfWorkManager : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
        internal DbContextScopedFreeSql _ormScoped;
 | 
			
		||||
        internal IFreeSql OrmOriginal => _ormScoped?._originalFsql;
 | 
			
		||||
        public IFreeSql Orm => _ormScoped;
 | 
			
		||||
        List<UowInfo> _rawUows = new List<UowInfo>();
 | 
			
		||||
        List<UowInfo> _allUows = new List<UowInfo>();
 | 
			
		||||
        List<RepoInfo> _repos = new List<RepoInfo>();
 | 
			
		||||
 | 
			
		||||
        public UnitOfWorkManager(IFreeSql fsql)
 | 
			
		||||
        {
 | 
			
		||||
            if (fsql == null) throw new ArgumentNullException(DbContextStrings.UnitOfWorkManager_Construction_CannotBeNull(nameof(UnitOfWorkManager), nameof(fsql)));
 | 
			
		||||
            _ormScoped = DbContextScopedFreeSql.Create(fsql, null, () => this.Current);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region Dispose
 | 
			
		||||
        ~UnitOfWorkManager() => this.Dispose();
 | 
			
		||||
        int _disposeCounter;
 | 
			
		||||
        public void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            if (Interlocked.Increment(ref _disposeCounter) != 1) return;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                Exception exception = null;
 | 
			
		||||
                for (var a = _rawUows.Count - 1; a >= 0; a--)
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        if (exception == null) _rawUows[a].Uow.Commit();
 | 
			
		||||
                        else _rawUows[a].Uow.Rollback();
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (Exception ex)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (exception == null) exception = ex;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                if (exception != null) throw exception;
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                _rawUows.Clear();
 | 
			
		||||
                _allUows.Clear();
 | 
			
		||||
                _repos.Clear();
 | 
			
		||||
                GC.SuppressFinalize(this);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 当前的工作单元
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IUnitOfWork Current => _allUows.LastOrDefault()?.Uow;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 将仓储的事务交给我管理
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="repository"></param>
 | 
			
		||||
        public void Binding(IBaseRepository repository)
 | 
			
		||||
        {
 | 
			
		||||
            var repoInfo = new RepoInfo(repository);
 | 
			
		||||
            repository.UnitOfWork = Current;
 | 
			
		||||
            if (_repos.Any(a => a.Repository == repository)) return;
 | 
			
		||||
            _repos.Add(repoInfo);
 | 
			
		||||
        }
 | 
			
		||||
        void SetAllRepositoryUow()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var repo in _repos)
 | 
			
		||||
                repo.Repository.UnitOfWork = Current ?? repo.OrginalUow;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 创建工作单元
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="propagation">事务传播方式</param>
 | 
			
		||||
        /// <param name="isolationLevel">事务隔离级别</param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public IUnitOfWork Begin(Propagation propagation = Propagation.Required, IsolationLevel? isolationLevel = null)
 | 
			
		||||
        {
 | 
			
		||||
            switch (propagation)
 | 
			
		||||
            {
 | 
			
		||||
                case Propagation.Required: return FindedUowCreateVirtual() ?? CreateUow(isolationLevel);
 | 
			
		||||
                case Propagation.Supports: return FindedUowCreateVirtual() ?? CreateUowNothing(_allUows.LastOrDefault()?.IsNotSupported ?? false);
 | 
			
		||||
                case Propagation.Mandatory: return FindedUowCreateVirtual() ?? throw new Exception(DbContextStrings.Propagation_Mandatory);
 | 
			
		||||
                case Propagation.NotSupported: return CreateUowNothing(true);
 | 
			
		||||
                case Propagation.Never:
 | 
			
		||||
                    var isNotSupported = _allUows.LastOrDefault()?.IsNotSupported ?? false;
 | 
			
		||||
                    if (isNotSupported == false)
 | 
			
		||||
                    {
 | 
			
		||||
                        for (var a = _rawUows.Count - 1; a >= 0; a--)
 | 
			
		||||
                            if (_rawUows[a].Uow.GetOrBeginTransaction(false) != null)
 | 
			
		||||
                                throw new Exception(DbContextStrings.Propagation_Never);
 | 
			
		||||
                    }
 | 
			
		||||
                    return CreateUowNothing(isNotSupported);
 | 
			
		||||
                case Propagation.Nested: return CreateUow(isolationLevel);
 | 
			
		||||
                default: throw new NotImplementedException();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        IUnitOfWork FindedUowCreateVirtual()
 | 
			
		||||
        {
 | 
			
		||||
            var isNotSupported = _allUows.LastOrDefault()?.IsNotSupported ?? false;
 | 
			
		||||
            if (isNotSupported == false)
 | 
			
		||||
            {
 | 
			
		||||
                for (var a = _rawUows.Count - 1; a >= 0; a--)
 | 
			
		||||
                    if (_rawUows[a].Uow.GetOrBeginTransaction(false) != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        var uow = new UnitOfWorkVirtual(_rawUows[a].Uow);
 | 
			
		||||
                        var uowInfo = new UowInfo(uow, UowInfo.UowType.Virtual, isNotSupported);
 | 
			
		||||
                        uow.OnDispose = () => _allUows.Remove(uowInfo);
 | 
			
		||||
                        _allUows.Add(uowInfo);
 | 
			
		||||
                        SetAllRepositoryUow();
 | 
			
		||||
                        return uow;
 | 
			
		||||
                    }
 | 
			
		||||
            }
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        IUnitOfWork CreateUowNothing(bool isNotSupported)
 | 
			
		||||
        {
 | 
			
		||||
            var uow = new UnitOfWorkNothing(Orm);
 | 
			
		||||
            var uowInfo = new UowInfo(uow, UowInfo.UowType.Nothing, isNotSupported);
 | 
			
		||||
            uow.OnDispose = () => _allUows.Remove(uowInfo);
 | 
			
		||||
            _allUows.Add(uowInfo);
 | 
			
		||||
            SetAllRepositoryUow();
 | 
			
		||||
            return uow;
 | 
			
		||||
        }
 | 
			
		||||
        IUnitOfWork CreateUow(IsolationLevel? isolationLevel)
 | 
			
		||||
        {
 | 
			
		||||
            var uow = new UnitOfWorkOrginal(new UnitOfWork(OrmOriginal));
 | 
			
		||||
            var uowInfo = new UowInfo(uow, UowInfo.UowType.Orginal, false);
 | 
			
		||||
            if (isolationLevel != null) uow.IsolationLevel = isolationLevel.Value;
 | 
			
		||||
            try { uow.GetOrBeginTransaction(); }
 | 
			
		||||
            catch { uow.Dispose(); throw; }
 | 
			
		||||
 | 
			
		||||
            uow.OnDispose = () =>
 | 
			
		||||
            {
 | 
			
		||||
                _rawUows.Remove(uowInfo);
 | 
			
		||||
                _allUows.Remove(uowInfo);
 | 
			
		||||
                SetAllRepositoryUow();
 | 
			
		||||
            };
 | 
			
		||||
            _rawUows.Add(uowInfo);
 | 
			
		||||
            _allUows.Add(uowInfo);
 | 
			
		||||
            SetAllRepositoryUow();
 | 
			
		||||
            return uow;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        class RepoInfo
 | 
			
		||||
        {
 | 
			
		||||
            public IBaseRepository Repository;
 | 
			
		||||
            public IUnitOfWork OrginalUow;
 | 
			
		||||
 | 
			
		||||
            public RepoInfo(IBaseRepository repository)
 | 
			
		||||
            {
 | 
			
		||||
                this.Repository = repository;
 | 
			
		||||
                this.OrginalUow = repository.UnitOfWork;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        class UowInfo
 | 
			
		||||
        {
 | 
			
		||||
            public IUnitOfWork Uow;
 | 
			
		||||
            public UowType Type;
 | 
			
		||||
            public bool IsNotSupported;
 | 
			
		||||
            public enum UowType { Orginal, Virtual, Nothing }
 | 
			
		||||
 | 
			
		||||
            public UowInfo(IUnitOfWork uow, UowType type, bool isNotSupported)
 | 
			
		||||
            {
 | 
			
		||||
                this.Uow = uow;
 | 
			
		||||
                this.Type = type;
 | 
			
		||||
                this.IsNotSupported = isNotSupported;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        class UnitOfWorkOrginal : IUnitOfWork
 | 
			
		||||
        {
 | 
			
		||||
            IUnitOfWork _baseUow;
 | 
			
		||||
            internal Action OnDispose;
 | 
			
		||||
            public UnitOfWorkOrginal(IUnitOfWork baseUow) => _baseUow = baseUow;
 | 
			
		||||
            public IFreeSql Orm => _baseUow.Orm;
 | 
			
		||||
            public IsolationLevel? IsolationLevel { get => _baseUow.IsolationLevel; set => _baseUow.IsolationLevel = value; }
 | 
			
		||||
            public DbContext.EntityChangeReport EntityChangeReport => _baseUow.EntityChangeReport;
 | 
			
		||||
            public Dictionary<string, object> States => _baseUow.States;
 | 
			
		||||
 | 
			
		||||
            public DbTransaction GetOrBeginTransaction(bool isCreate = true) => _baseUow.GetOrBeginTransaction(isCreate);
 | 
			
		||||
            public void Commit() => _baseUow.Commit();
 | 
			
		||||
            public void Rollback() => _baseUow.Rollback();
 | 
			
		||||
            public void Dispose()
 | 
			
		||||
            {
 | 
			
		||||
                _baseUow.Dispose();
 | 
			
		||||
                OnDispose?.Invoke();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        class UnitOfWorkVirtual : IUnitOfWork
 | 
			
		||||
        {
 | 
			
		||||
            IUnitOfWork _baseUow;
 | 
			
		||||
            internal Action OnDispose;
 | 
			
		||||
            public UnitOfWorkVirtual(IUnitOfWork baseUow) => _baseUow = baseUow;
 | 
			
		||||
            public IFreeSql Orm => _baseUow.Orm;
 | 
			
		||||
            public IsolationLevel? IsolationLevel { get => _baseUow.IsolationLevel; set { } }
 | 
			
		||||
            public DbContext.EntityChangeReport EntityChangeReport => _baseUow.EntityChangeReport;
 | 
			
		||||
            public Dictionary<string, object> States => _baseUow.States;
 | 
			
		||||
 | 
			
		||||
            public DbTransaction GetOrBeginTransaction(bool isCreate = true) => _baseUow.GetOrBeginTransaction(isCreate);
 | 
			
		||||
            public void Commit() { }
 | 
			
		||||
            public void Rollback() => _baseUow.Rollback();
 | 
			
		||||
            public void Dispose() => OnDispose?.Invoke();
 | 
			
		||||
        }
 | 
			
		||||
        class UnitOfWorkNothing : IUnitOfWork
 | 
			
		||||
        {
 | 
			
		||||
            internal IFreeSql _fsql;
 | 
			
		||||
            internal Action OnDispose;
 | 
			
		||||
            public UnitOfWorkNothing(IFreeSql fsql) => _fsql = fsql;
 | 
			
		||||
            public IFreeSql Orm => _fsql;
 | 
			
		||||
            public IsolationLevel? IsolationLevel { get; set; }
 | 
			
		||||
            public DbContext.EntityChangeReport EntityChangeReport { get; } = new DbContext.EntityChangeReport();
 | 
			
		||||
            public Dictionary<string, object> States { get; } = new Dictionary<string, object>();
 | 
			
		||||
 | 
			
		||||
            public DbTransaction GetOrBeginTransaction(bool isCreate = true) => null;
 | 
			
		||||
            public void Commit()
 | 
			
		||||
            {
 | 
			
		||||
                if (EntityChangeReport != null && EntityChangeReport.OnChange != null && EntityChangeReport.Report.Any() == true)
 | 
			
		||||
                    EntityChangeReport.OnChange.Invoke(EntityChangeReport.Report);
 | 
			
		||||
                EntityChangeReport?.Report.Clear();
 | 
			
		||||
            }
 | 
			
		||||
            public void Rollback() => EntityChangeReport?.Report.Clear();
 | 
			
		||||
            public void Dispose() => OnDispose?.Invoke();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 事务传播方式
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public enum Propagation
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,默认的选择。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        Required,
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 支持当前事务,如果没有当前事务,就以非事务方法执行。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        Supports,
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 使用当前事务,如果没有当前事务,就抛出异常。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        Mandatory,
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        NotSupported,
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 以非事务方式执行操作,如果当前事务存在则抛出异常。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        Never,
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 以嵌套事务方式执行。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        Nested
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user