using System; using System.Collections.Generic; using System.Dynamic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading; using System.Threading.Tasks; namespace SqlSugar { public partial class SqlSugarClient : ISqlSugarClient, ITenant { #region Gobal Property private SqlSugarProvider _Context = null; private string _ThreadId; private ConnectionConfig _CurrentConnectionConfig; private List _AllClients; private bool _IsAllTran = false; private bool _IsOpen = false; private MappingTableList _MappingTables; private MappingColumnList _MappingColumns; private IgnoreColumnList _IgnoreColumns; private IgnoreColumnList _IgnoreInsertColumns; internal Guid? AsyncId { get; set; } internal bool? IsSingleInstance { get; set; } #endregion #region Constructor public SqlSugarClient(ConnectionConfig config) { Check.Exception(config == null, "ConnectionConfig config is null"); InitContext(config); } public SqlSugarClient(List configs) { Check.Exception(configs.IsNullOrEmpty(), "List configs is null"); InitConfigs(configs); var config = configs.First(); InitContext(config); _AllClients = configs.Select(it => new SugarTenant() { ConnectionConfig = it }).ToList(); ; _AllClients.First(it => it.ConnectionConfig.ConfigId == config.ConfigId).Context = this.Context; } #endregion #region Global variable public SqlSugarProvider Context { get { return GetContext(); } } public bool IsSystemTablesConfig => this.Context.IsSystemTablesConfig; public ConnectionConfig CurrentConnectionConfig { get { return _CurrentConnectionConfig; } set { _CurrentConnectionConfig = value; } } public Guid ContextID { get { return this.Context.ContextID; } set { this.Context.ContextID = value; } } public MappingTableList MappingTables { get { return _MappingTables; } set { _MappingTables = value; } } public MappingColumnList MappingColumns { get { return _MappingColumns; } set { _MappingColumns = value; } } public IgnoreColumnList IgnoreColumns { get { return _IgnoreColumns; } set { _IgnoreColumns = value; } } public IgnoreColumnList IgnoreInsertColumns { get { return _IgnoreInsertColumns; } set { _IgnoreInsertColumns = value; } } public Dictionary TempItems { get { return this.Context.TempItems; } set { this.Context.TempItems = value; } } #endregion #region SimpleClient public SimpleClient GetSimpleClient() { return this.Context.GetSimpleClient(); } public SimpleClient GetSimpleClient() where T : class, new() { return this.Context.GetSimpleClient(); } #endregion #region Insertable public IInsertable Insertable(Dictionary columnDictionary) where T : class, new() { return this.Context.Insertable(columnDictionary); } public IInsertable Insertable(dynamic insertDynamicObject) where T : class, new() { return this.Context.Insertable(insertDynamicObject); } public IInsertable Insertable(List insertObjs) where T : class, new() { return this.Context.Insertable(insertObjs); } public IInsertable Insertable(T insertObj) where T : class, new() { return this.Context.Insertable(insertObj); } public IInsertable Insertable(T[] insertObjs) where T : class, new() { return this.Context.Insertable(insertObjs); } #endregion #region Queryable #region Union public ISugarQueryable Union(List> queryables) where T : class, new() { return this.Context.Union(queryables); } public ISugarQueryable Union(params ISugarQueryable[] queryables) where T : class, new() { return this.Context.Union(queryables); } public ISugarQueryable UnionAll(List> queryables) where T : class, new() { return this.Context.UnionAll(queryables); } public ISugarQueryable UnionAll(params ISugarQueryable[] queryables) where T : class, new() { return this.Context.UnionAll(queryables); } #endregion public ISugarQueryable SqlQueryable(string sql) where T : class, new() { return this.Context.SqlQueryable(sql); } public ISugarQueryable Queryable(string tableName, string shortName) { return this.Context.Queryable(tableName, shortName); } public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(Expression> joinExpression) { return this.Context.Queryable(joinExpression); } public ISugarQueryable Queryable(ISugarQueryable joinQueryable1, ISugarQueryable joinQueryable2, Expression> joinExpression) where T : class, new() where T2 : class, new() { return this.Context.Queryable(joinQueryable1, joinQueryable2, joinExpression); } public ISugarQueryable Queryable(ISugarQueryable joinQueryable1, ISugarQueryable joinQueryable2, JoinType joinType, Expression> joinExpression) where T : class, new() where T2 : class, new() { return this.Context.Queryable(joinQueryable1, joinQueryable2, joinType, joinExpression); } public ISugarQueryable Queryable() { return this.Context.Queryable(); } public ISugarQueryable Queryable(ISugarQueryable queryable) where T : class, new() { return this.Context.Queryable(queryable); } public ISugarQueryable Queryable(string shortName) { return this.Context.Queryable(shortName); } #endregion #region Saveable public ISaveable Saveable(List saveObjects) where T : class, new() { return this.Context.Saveable(saveObjects); } public ISaveable Saveable(T saveObject) where T : class, new() { return this.Context.Saveable(saveObject); } #endregion #region Queue public QueueList Queues { get { return this.Context.Queues; } set { this.Context.Queues = value; } } public void AddQueue(string sql, object parsmeters = null) { this.Context.AddQueue(sql, parsmeters); } public void AddQueue(string sql, List parsmeters) { this.Context.AddQueue(sql, parsmeters); } public void AddQueue(string sql, SugarParameter parsmeter) { this.Context.AddQueue(sql, parsmeter); } public int SaveQueues(bool isTran = true) { return this.Context.SaveQueues(isTran); } public Tuple, List, List, List, List, List, List> SaveQueues(bool isTran = true) { return this.Context.SaveQueues(isTran); } public Tuple, List, List, List, List, List> SaveQueues(bool isTran = true) { return this.Context.SaveQueues(isTran); } public Tuple, List, List, List, List> SaveQueues(bool isTran = true) { return this.Context.SaveQueues(isTran); } public Tuple, List, List, List> SaveQueues(bool isTran = true) { return this.Context.SaveQueues(isTran); } public Tuple, List, List> SaveQueues(bool isTran = true) { return this.Context.SaveQueues(isTran); } public Tuple, List> SaveQueues(bool isTran = true) { return this.Context.SaveQueues(isTran); } public List SaveQueues(bool isTran = true) { return this.Context.SaveQueues(isTran); } public Task SaveQueuesAsync(bool isTran = true) { return this.Context.SaveQueuesAsync(isTran); } public Task, List, List, List, List, List, List>> SaveQueuesAsync(bool isTran = true) { return this.Context.SaveQueuesAsync(isTran); } public Task, List, List, List, List, List>> SaveQueuesAsync(bool isTran = true) { return this.Context.SaveQueuesAsync(isTran); } public Task, List, List, List, List>> SaveQueuesAsync(bool isTran = true) { return this.Context.SaveQueuesAsync(isTran); } public Task, List, List, List>> SaveQueuesAsync(bool isTran = true) { return this.Context.SaveQueuesAsync(isTran); } public Task, List, List>> SaveQueuesAsync(bool isTran = true) { return this.Context.SaveQueuesAsync(isTran); } public Task, List>> SaveQueuesAsync(bool isTran = true) { return this.Context.SaveQueuesAsync(isTran); } public Task> SaveQueuesAsync(bool isTran = true) { return this.Context.SaveQueuesAsync(isTran); } #endregion #region Updateable public IUpdateable Updateable() where T : class, new() { return this.Context.Updateable(); } public IUpdateable Updateable(Dictionary columnDictionary) where T : class, new() { return this.Context.Updateable(columnDictionary); } public IUpdateable Updateable(dynamic updateDynamicObject) where T : class, new() { return this.Context.Updateable(updateDynamicObject); } public IUpdateable Updateable(Expression> columns) where T : class, new() { return this.Context.Updateable(columns); } public IUpdateable Updateable(Expression> columns) where T : class, new() { return this.Context.Updateable(columns); } public IUpdateable Updateable(List UpdateObjs) where T : class, new() { return this.Context.Updateable(UpdateObjs); } public IUpdateable Updateable(T UpdateObj) where T : class, new() { return this.Context.Updateable(UpdateObj); } public IUpdateable Updateable(T[] UpdateObjs) where T : class, new() { return this.Context.Updateable(UpdateObjs); } #endregion #region Ado public IAdo Ado => this.Context.Ado; #endregion #region Deleteable public IDeleteable Deleteable() where T : class, new() { return this.Context.Deleteable(); } public IDeleteable Deleteable(dynamic primaryKeyValue) where T : class, new() { return this.Context.Deleteable(primaryKeyValue); } public IDeleteable Deleteable(dynamic[] primaryKeyValues) where T : class, new() { return this.Context.Deleteable(primaryKeyValues); } public IDeleteable Deleteable(Expression> expression) where T : class, new() { return this.Context.Deleteable(expression); } public IDeleteable Deleteable(List pkValue) where T : class, new() { return this.Context.Deleteable(pkValue); } public IDeleteable Deleteable(List deleteObjs) where T : class, new() { return this.Context.Deleteable(deleteObjs); } public IDeleteable Deleteable(T deleteObj) where T : class, new() { return this.Context.Deleteable(deleteObj); } #endregion #region More api public IContextMethods Utilities { get { return this.Context.Utilities; } set { this.Context.Utilities = value; } } public AopProvider Aop => this.Context.Aop; public ICodeFirst CodeFirst => this.Context.CodeFirst; public IDbFirst DbFirst => this.Context.DbFirst; public IDbMaintenance DbMaintenance => this.Context.DbMaintenance; public EntityMaintenance EntityMaintenance { get { return this.Context.EntityMaintenance; } set { this.Context.EntityMaintenance = value; } } public QueryFilterProvider QueryFilter { get { return this.Context.QueryFilter; }set { this.Context.QueryFilter = value; } } #endregion #region TenantManager public void ChangeDatabase(string configId) { Check.Exception(!_AllClients.Any(it => it.ConnectionConfig.ConfigId == configId), "ConfigId was not found {0}", configId); InitTenant(_AllClients.First(it => it.ConnectionConfig.ConfigId == configId)); if (this._IsAllTran) this.Ado.BeginTran(); if (this._IsOpen) this.Open(); } public void ChangeDatabase(Func changeExpression) { var allConfigs = _AllClients.Select(it => it.ConnectionConfig); Check.Exception(!allConfigs.Any(changeExpression), "changeExpression was not found {0}", changeExpression.ToString()); InitTenant(_AllClients.First(it => it.ConnectionConfig == allConfigs.First(changeExpression))); if (this._IsAllTran) this.Ado.BeginTran(); if (this._IsOpen) this.Open(); } public void BeginTran() { _IsAllTran = true; this.Context.Ado.BeginTran(); } public void CommitTran() { this.Context.Ado.CommitTran(); AllClientEach(it => it.Ado.CommitTran()); _IsAllTran = false; } public DbResult UseTran(Action action, Action errorCallBack = null) { var result = new DbResult(); try { this.BeginTran(); if (action != null) action(); this.CommitTran(); result.Data = result.IsSuccess = true; } catch (Exception ex) { result.ErrorException = ex; result.ErrorMessage = ex.Message; result.IsSuccess = false; this.RollbackTran(); if (errorCallBack != null) { errorCallBack(ex); } } return result; } public Task> UseTranAsync(Action action, Action errorCallBack = null) { return Task.FromResult(UseTran(action, errorCallBack)); } public DbResult UseTran(Func action, Action errorCallBack = null) { var result = new DbResult(); try { this.BeginTran(); if (action != null) result.Data = action(); this.CommitTran(); result.IsSuccess = true; } catch (Exception ex) { result.ErrorException = ex; result.ErrorMessage = ex.Message; result.IsSuccess = false; this.RollbackTran(); if (errorCallBack != null) { errorCallBack(ex); } } return result; } public Task> UseTranAsync(Func action, Action errorCallBack = null) { return Task.FromResult(UseTran(action, errorCallBack)); } public void RollbackTran() { this.Context.Ado.RollbackTran(); AllClientEach(it => it.Ado.RollbackTran()); _IsAllTran = false; } public void Close() { this.Context.Close(); AllClientEach(it => it.Close()); _IsOpen = false; } public void Open() { this.Context.Open(); _IsOpen = true; } #endregion #region IDispose public void Dispose() { this.Context.Dispose(); AllClientEach(it => it.Ado.RollbackTran()); } #endregion #region Other method public DateTime GetDate() { return this.Context.GetDate(); } public void InitMappingInfo(Type type) { this.Context.InitMappingInfo(type); } public void InitMappingInfo() { this.Context.InitMappingInfo(typeof(T)); } #endregion #region Helper private SqlSugarProvider GetContext() { SqlSugarProvider result = null; if (IsSameThreadAndShard()) { result = SameThreadAndShard(); } else if (IsNoSameThreadAndShard()) { result = NoSameThreadAndShard(); } else if (IsSynchronization()) { result = Synchronization(); } else if (IsSingleInstanceAsync()) { result = NoSameThreadAsync(); } else if (IsAsync()) { result = Synchronization(); } else { IsSingleInstance = true; result = NoSameThread(); } if (result.Root == null) { result.Root = this; } return result; } private SqlSugarProvider NoSameThreadAsync() { var result = GetCallContext(); return result; } private SqlSugarProvider NoSameThread() { if (CallContext.ContextList.Value == null) { var context = CopyClient(); AddCallContext(context); return context; } else { var result = GetCallContext(); if (result == null) { var copy = CopyClient(); AddCallContext(copy); return copy; } else { return result; } } } private SqlSugarProvider Synchronization() { _Context.MappingColumns = _MappingColumns; _Context.MappingTables = _MappingTables; _Context.IgnoreColumns = _IgnoreColumns; _Context.IgnoreInsertColumns = _IgnoreInsertColumns; return _Context; } private SqlSugarProvider NoSameThreadAndShard() { if (CallContext.ContextList.Value.IsNullOrEmpty()) { var copy = CopyClient(); AddCallContext(copy); return copy; } else { var result = GetCallContext(); if (result == null) { var copy = CopyClient(); AddCallContext(copy); return copy; } else { return result; } } } private SqlSugarProvider SameThreadAndShard() { if (CallContext.ContextList.Value.IsNullOrEmpty()) { AddCallContext(_Context); return _Context; } else { var result = GetCallContext(); if (result == null) { var copy = CopyClient(); AddCallContext(copy); return copy; } else { return result; } } } private bool IsAsync() { return AsyncId != null; } private bool IsSingleInstanceAsync() { return IsSingleInstance == true && AsyncId != null; } private bool IsSynchronization() { return _ThreadId == Thread.CurrentThread.ManagedThreadId.ToString(); } private bool IsNoSameThreadAndShard() { return CurrentConnectionConfig.IsShardSameThread && _ThreadId != Thread.CurrentThread.ManagedThreadId.ToString(); } private bool IsSameThreadAndShard() { return CurrentConnectionConfig.IsShardSameThread && _ThreadId == Thread.CurrentThread.ManagedThreadId.ToString(); } private SqlSugarProvider CopyClient() { var result = new SqlSugarProvider(this.CurrentConnectionConfig); result.MappingColumns = _MappingColumns; result.MappingTables = _MappingTables; result.IgnoreColumns = _IgnoreColumns; result.IgnoreInsertColumns = _IgnoreInsertColumns; return result; } private void AddCallContext(SqlSugarProvider context) { CallContext.ContextList.Value = new List(); CallContext.ContextList.Value.Add(context); } private SqlSugarProvider GetCallContext() { return CallContext.ContextList.Value.FirstOrDefault(it => it.CurrentConnectionConfig.DbType == _Context.CurrentConnectionConfig.DbType && it.CurrentConnectionConfig.ConnectionString == _Context.CurrentConnectionConfig.ConnectionString && it.CurrentConnectionConfig.InitKeyType == _Context.CurrentConnectionConfig.InitKeyType && it.CurrentConnectionConfig.IsAutoCloseConnection == _Context.CurrentConnectionConfig.IsAutoCloseConnection ); } private void InitContext(ConnectionConfig config) { var aopIsNull = config.AopEvents == null; if (aopIsNull) { config.AopEvents = new AopEvents(); } _Context = new SqlSugarProvider(config); if (!aopIsNull) _Context.Ado.IsEnableLogEvent = true; this.CurrentConnectionConfig = config; _ThreadId = Thread.CurrentThread.ManagedThreadId.ToString(); if (_MappingColumns == null) this.MappingTables = new MappingTableList(); if (this.MappingColumns == null) this.MappingColumns = new MappingColumnList(); if (this.IgnoreColumns == null) this.IgnoreColumns = new IgnoreColumnList(); if (this.IgnoreInsertColumns == null) this.IgnoreInsertColumns = new IgnoreColumnList(); } private void InitConfigs(List configs) { foreach (var item in configs) { if (item.ConfigId == null) { item.ConfigId = Guid.NewGuid().ToString(); } } } private void AllClientEach(Action action) { if (_AllClients.HasValue()) { foreach (var item in _AllClients.Where(it => it.Context.HasValue())) { action(item.Context); } } } private void InitTenant(SugarTenant Tenant) { if (Tenant.Context == null) { Tenant.Context = new SqlSugarProvider(Tenant.ConnectionConfig); } _Context = Tenant.Context; this.CurrentConnectionConfig = Tenant.ConnectionConfig; } #endregion #region Obsolete [Obsolete("Use EntityMaintenance")] public EntityMaintenance EntityProvider { get { return this.Context.EntityProvider; } set { this.Context.EntityProvider = value; } } [Obsolete("Use Utilities")] public IContextMethods RewritableMethods { get { return this.Context.RewritableMethods; } set { this.Context.RewritableMethods = value; } } [Obsolete("Use GetSimpleClient")] public SimpleClient SimpleClient { get { return this.Context.SimpleClient; } } #endregion } }