using FreeSql; using FreeSql.Internal; using FreeSql.Internal.CommonProvider; using FreeSql.Internal.Model; using FreeSql.Internal.ObjectPool; using System; using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Text; namespace FreeSql { class DbContextScopedFreeSql : IFreeSql { public IFreeSql _originalFsql; Func _resolveDbContext; Func _resolveUnitOfWork; DbContextScopedFreeSql() { } public static DbContextScopedFreeSql Create(IFreeSql fsql, Func resolveDbContext, Func resolveUnitOfWork) { if (fsql == null) return null; var scopedfsql = fsql as DbContextScopedFreeSql; if (scopedfsql == null) return new DbContextScopedFreeSql { _originalFsql = fsql, _resolveDbContext = resolveDbContext, _resolveUnitOfWork = resolveUnitOfWork, Ado = new ScopeTransactionAdo(fsql.Ado as AdoProvider, () => { var db = resolveDbContext?.Invoke(); db?.FlushCommand(); return resolveUnitOfWork?.Invoke()?.GetOrBeginTransaction(); }) }; return Create(scopedfsql._originalFsql, resolveDbContext, resolveUnitOfWork); } class ScopeTransactionAdo : AdoProvider { AdoProvider _ado; public ScopeTransactionAdo(AdoProvider ado, Func resolveTran) : base(ado.DataType, null, null) { _ado = ado; base.ResolveTransaction = resolveTran; base.ConnectionString = ado.ConnectionString; base.SlaveConnectionStrings = ado.SlaveConnectionStrings; base.Identifier = ado.Identifier; base.MasterPool = ado.MasterPool; base._util = ado._util; } public override object AddslashesProcessParam(object param, Type mapType, ColumnInfo mapColumn) => _ado.AddslashesProcessParam(param, mapType, mapColumn); public override DbCommand CreateCommand() => _ado.CreateCommand(); public override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _ado.GetDbParamtersByObject(sql, obj); public override void ReturnConnection(IObjectPool pool, Object conn, Exception ex) => _ado.ReturnConnection(pool, conn, ex); } public IAdo Ado { get; private set; } public IAop Aop => _originalFsql.Aop; public ICodeFirst CodeFirst => _originalFsql.CodeFirst; public IDbFirst DbFirst => _originalFsql.DbFirst; public GlobalFilter GlobalFilter => _originalFsql.GlobalFilter; public void Dispose() { } public void Transaction(Action handler) => _originalFsql.Transaction(handler); public void Transaction(IsolationLevel isolationLevel, Action handler) => _originalFsql.Transaction(isolationLevel, handler); public ISelect Select() where T1 : class { var db = _resolveDbContext?.Invoke(); db?.FlushCommand(); var uow = _resolveUnitOfWork?.Invoke(); var uowIsolationLevel = uow?.IsolationLevel ?? IsolationLevel.Unspecified; var select = _originalFsql.Select().WithTransaction(uow?.GetOrBeginTransaction(uowIsolationLevel != IsolationLevel.Unspecified)); (select as Select0Provider)._resolveHookTransaction = () => uow?.GetOrBeginTransaction(); if (db?.Options.EnableGlobalFilter == false) select.DisableGlobalFilter(); return select; } public ISelect Select(object dywhere) where T1 : class => Select().WhereDynamic(dywhere); public IDelete Delete() where T1 : class { var db = _resolveDbContext?.Invoke(); db?.FlushCommand(); var delete = _originalFsql.Delete().WithTransaction(_resolveUnitOfWork?.Invoke()?.GetOrBeginTransaction()); if (db?.Options.EnableGlobalFilter == false) delete.DisableGlobalFilter(); return delete; } public IDelete Delete(object dywhere) where T1 : class => Delete().WhereDynamic(dywhere); public IUpdate Update() where T1 : class { var db = _resolveDbContext?.Invoke(); db?.FlushCommand(); var update = _originalFsql.Update().WithTransaction(_resolveUnitOfWork?.Invoke()?.GetOrBeginTransaction()); if (db?.Options.NoneParameter != null) update.NoneParameter(db.Options.NoneParameter.Value); if (db?.Options.EnableGlobalFilter == false) update.DisableGlobalFilter(); return update; } public IUpdate Update(object dywhere) where T1 : class => Update().WhereDynamic(dywhere); public IInsert Insert() where T1 : class { var db = _resolveDbContext?.Invoke(); db?.FlushCommand(); var insert = _originalFsql.Insert().WithTransaction(_resolveUnitOfWork?.Invoke()?.GetOrBeginTransaction()); if (db?.Options.NoneParameter != null) insert.NoneParameter(db.Options.NoneParameter.Value); return insert; } public IInsert Insert(T1 source) where T1 : class => Insert().AppendData(source); public IInsert Insert(T1[] source) where T1 : class => Insert().AppendData(source); public IInsert Insert(List source) where T1 : class => Insert().AppendData(source); public IInsert Insert(IEnumerable source) where T1 : class => Insert().AppendData(source); public IInsertOrUpdate InsertOrUpdate() where T1 : class { var db = _resolveDbContext?.Invoke(); db?.FlushCommand(); return _originalFsql.InsertOrUpdate().WithTransaction(_resolveUnitOfWork?.Invoke()?.GetOrBeginTransaction()); } } }