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; /// /// 正在使用中的工作单元(调试) /// public static ConcurrentDictionary DebugBeingUsed { get; } = new ConcurrentDictionary(); protected IFreeSql _fsql; protected Object _conn; protected DbTransaction _tran; protected Aop.TraceBeforeEventArgs _tranBefore; protected Aop.TraceBeforeEventArgs _uowBefore; /// /// 开启事务后有值,是 UnitOfWork 的唯一标识 /// 格式:yyyyMMdd_HHmmss_种子id /// 例如:20191121_214504_1 /// 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("已开启事务,不能禁用工作单元"); Enable = false; } public void Open() { Enable = true; } 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)); throw ex; } return _tran; } public void Commit() { var isCommited = false; try { if (_tran != 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)); throw ex; } finally { ReturnObject(); _tranBefore = null; } } public void Rollback() { var isRollbacked = false; try { if (_tran != 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)); throw ex; } finally { ReturnObject(); _tranBefore = null; } } public DbContext.EntityChangeReport EntityChangeReport { get; } = new DbContext.EntityChangeReport(); ~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); } } } }