using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace SqlSugar { public partial class SqlSugarProvider { #region Properties public SqlSugarProvider Context { get { _Context = this; return _Context; } set { _Context = value; } } public SqlSugarClient Root { get; set; } public ConnectionConfig CurrentConnectionConfig { get; set; } public Dictionary TempItems { get { if (_TempItems == null) { _TempItems = new Dictionary(); } return _TempItems; } set { _TempItems = value; } } public bool IsSystemTablesConfig { get { return this.CurrentConnectionConfig.InitKeyType == InitKeyType.SystemTable; } } public Guid ContextID { get; set; } public MappingTableList MappingTables { get; set; } public MappingColumnList MappingColumns { get; set; } public IgnoreColumnList IgnoreColumns { get; set; } public IgnoreColumnList IgnoreInsertColumns { get; set; } public SugarActionType SugarActionType { get; set; } = SugarActionType.UnKnown; public ConfigQuery ConfigQuery { get { if (_SqlConfigTable==null) { _SqlConfigTable = new ConfigQuery() { Context = this.Context }; } return _SqlConfigTable; } set { _SqlConfigTable = value; } } #endregion #region Fields public Dictionary _TempItems; public QueueList _Queues; protected ISqlBuilder _SqlBuilder; protected SqlSugarProvider _Context { get; set; } protected EntityMaintenance _EntityProvider; protected IAdo _Ado; protected ILambdaExpressions _LambdaExpressions; protected IContextMethods _RewritableMethods; protected IDbMaintenance _DbMaintenance; protected QueryFilterProvider _QueryFilterProvider; protected ConfigQuery _SqlConfigTable; //protected SimpleClient _SimpleClient; protected IAdo ContextAdo { get { return this._Ado; } set { this._Ado = value; } } protected IContextMethods ContextRewritableMethods { get { return this._RewritableMethods; } set { this._RewritableMethods = value; } } #endregion #region Init mappingInfo protected void InitMappingInfo() { InitMappingInfo(); InitMappingInfo(); } protected void InitMappingInfo() { InitMappingInfo(); InitMappingInfo(); } protected void InitMappingInfo() { InitMappingInfo(); InitMappingInfo(); } protected void InitMappingInfo() { InitMappingInfo(); InitMappingInfo(); } protected void InitMappingInfo() { InitMappingInfo(); InitMappingInfo(); } protected void InitMappingInfo() { InitMappingInfo(); InitMappingInfo(); } protected void InitMappingInfo() { InitMappingInfo(); InitMappingInfo(); } #region 9-12 protected void InitMappingInfo() { InitMappingInfo(); InitMappingInfo(); } protected void InitMappingInfo() { InitMappingInfo(); InitMappingInfo(); } protected void InitMappingInfo() { InitMappingInfo(); InitMappingInfo(); } protected void InitMappingInfo() { InitMappingInfo(); InitMappingInfo(); } #endregion public void InitMappingInfo() { InitMappingInfo(typeof(T)); } public void InitMappingInfo(Type type) { string cacheKey = "Context.InitAttributeMappingTables" + type.FullName; var entityInfo = this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, () => { var result = this.Context.EntityMaintenance.GetEntityInfo(type); return result; }); //var copyObj = CopyEntityInfo(entityInfo); InitMappingInfo(entityInfo); } public void InitMappingInfoNoCache(Type type) { var entityInfo = this.Context.EntityMaintenance.GetEntityInfoNoCache(type); InitMappingInfo(entityInfo); } //private EntityInfo CopyEntityInfo(EntityInfo entityInfo) //{ // EntityInfo result = new EntityInfo() // { // DbTableName = entityInfo.DbTableName, // EntityName = entityInfo.EntityName, // Type = entityInfo.Type // }; // List columns = new List(); // if (entityInfo.Columns.HasValue()) // { // foreach (var item in entityInfo.Columns) // { // EntityColumnInfo column = new EntityColumnInfo() // { // ColumnDescription = item.ColumnDescription, // DataType = item.DataType, // DbColumnName = item.DbColumnName, // DbTableName = item.DbTableName, // DecimalDigits = item.DecimalDigits, // DefaultValue = item.DefaultValue, // EntityName = item.EntityName, // IsIdentity = item.IsIdentity, // IsIgnore = item.IsIgnore, // IsNullable = item.IsNullable, // IsOnlyIgnoreInsert = item.IsOnlyIgnoreInsert, // IsPrimarykey = item.IsPrimarykey, // Length = item.Length, // OldDbColumnName = item.OldDbColumnName, // OracleSequenceName = item.OracleSequenceName, // PropertyInfo = item.PropertyInfo, // PropertyName = item.PropertyName, // IsArray=item.IsArray, // IsJson=item.IsJson // }; // columns.Add(item); // } // } // result.Columns = columns; // return result; //} private void InitMappingInfo(EntityInfo entityInfo) { if (this.MappingTables == 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(); if (!this.MappingTables.Any(it => it.EntityName == entityInfo.EntityName)) { if (entityInfo.DbTableName != entityInfo.EntityName && entityInfo.DbTableName.HasValue()) { this.MappingTables.Add(entityInfo.EntityName, entityInfo.DbTableName); } } if (entityInfo.Columns.Any(it => it.EntityName == entityInfo.EntityName)) { var mappingColumnInfos = this.MappingColumns.Where(it => it.EntityName == entityInfo.EntityName); foreach (var item in entityInfo.Columns.Where(it => it.IsIgnore == false)) { if (!mappingColumnInfos.Any(it => it.PropertyName == item.PropertyName)) if (item.PropertyName != item.DbColumnName && item.DbColumnName.HasValue()) this.MappingColumns.Add(item.PropertyName, item.DbColumnName, item.EntityName); } var ignoreInfos = this.IgnoreColumns.Where(it => it.EntityName == entityInfo.EntityName); foreach (var item in entityInfo.Columns.Where(it => it.IsIgnore)) { if (!ignoreInfos.Any(it => it.PropertyName == item.PropertyName)) this.IgnoreColumns.Add(item.PropertyName, item.EntityName); } var ignoreInsertInfos = this.IgnoreInsertColumns.Where(it => it.EntityName == entityInfo.EntityName); foreach (var item in entityInfo.Columns.Where(it => it.IsOnlyIgnoreInsert)) { if (!ignoreInsertInfos.Any(it => it.PropertyName == item.PropertyName)) this.IgnoreInsertColumns.Add(item.PropertyName, item.EntityName); } } } #endregion #region Create Instance protected ISugarQueryable CreateQueryable() { ISugarQueryable result = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); return CreateQueryable(result); } protected ISugarQueryable CreateQueryable(ISugarQueryable result) { this.SugarActionType = SugarActionType.Query; Check.Exception(typeof(T).IsClass() == false || typeof(T).GetConstructors().Length == 0, "Queryable<{0}> Error ,{0} is invalid , need is a class,and can new().", typeof(T).Name); var sqlBuilder = InstanceFactory.GetSqlbuilder(CurrentConnectionConfig); result.Context = this.Context; result.SqlBuilder = sqlBuilder; result.SqlBuilder.QueryBuilder = InstanceFactory.GetQueryBuilder(CurrentConnectionConfig); result.SqlBuilder.QueryBuilder.Builder = sqlBuilder; result.SqlBuilder.Context = result.SqlBuilder.QueryBuilder.Context = this; result.SqlBuilder.QueryBuilder.EntityType = typeof(T); result.SqlBuilder.QueryBuilder.EntityName = typeof(T).Name; result.SqlBuilder.QueryBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(CurrentConnectionConfig); return result; } protected InsertableProvider CreateInsertable(T[] insertObjs) where T : class, new() { this.SugarActionType = SugarActionType.Insert; var result = InstanceFactory.GetInsertableProvider(this.CurrentConnectionConfig); var sqlBuilder = InstanceFactory.GetSqlbuilder(this.CurrentConnectionConfig); ; result.Context = this; result.EntityInfo = this.Context.EntityMaintenance.GetEntityInfo(); result.SqlBuilder = sqlBuilder; result.InsertObjs = insertObjs; sqlBuilder.InsertBuilder = result.InsertBuilder = InstanceFactory.GetInsertBuilder(this.CurrentConnectionConfig); sqlBuilder.InsertBuilder.Builder = sqlBuilder; sqlBuilder.InsertBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(this.CurrentConnectionConfig); sqlBuilder.Context = result.SqlBuilder.InsertBuilder.Context = this; result.Init(); return result; } protected DeleteableProvider CreateDeleteable() where T : class, new() { this.SugarActionType = SugarActionType.Delete; var result = InstanceFactory.GetDeleteableProvider(this.CurrentConnectionConfig); var sqlBuilder = InstanceFactory.GetSqlbuilder(this.CurrentConnectionConfig); ; result.Context = this; result.SqlBuilder = sqlBuilder; sqlBuilder.DeleteBuilder = result.DeleteBuilder = InstanceFactory.GetDeleteBuilder(this.CurrentConnectionConfig); sqlBuilder.DeleteBuilder.Builder = sqlBuilder; sqlBuilder.DeleteBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(this.CurrentConnectionConfig); sqlBuilder.Context = result.SqlBuilder.DeleteBuilder.Context = this; return result; } protected UpdateableProvider CreateUpdateable(T[] UpdateObjs) where T : class, new() { this.SugarActionType = SugarActionType.Update; var result = InstanceFactory.GetUpdateableProvider(this.CurrentConnectionConfig); var sqlBuilder = InstanceFactory.GetSqlbuilder(this.CurrentConnectionConfig); ; result.Context = this; result.EntityInfo = this.Context.EntityMaintenance.GetEntityInfo(); result.SqlBuilder = sqlBuilder; result.UpdateObjs = UpdateObjs; sqlBuilder.UpdateBuilder = result.UpdateBuilder = InstanceFactory.GetUpdateBuilder(this.CurrentConnectionConfig); sqlBuilder.UpdateBuilder.Builder = sqlBuilder; sqlBuilder.UpdateBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(this.CurrentConnectionConfig); sqlBuilder.Context = result.SqlBuilder.UpdateBuilder.Context = this; result.Init(); return result; } protected void CreateQueryJoin(Expression joinExpression, Type[] types, ISugarQueryable queryable) { this.SugarActionType = SugarActionType.Query; this.CreateQueryable(queryable); string shortName = string.Empty; List paramters = new List(); queryable.SqlBuilder.QueryBuilder.JoinQueryInfos = this.GetJoinInfos(queryable.SqlBuilder, joinExpression, ref paramters, ref shortName, types); if (queryable.SqlBuilder.QueryBuilder.JoinQueryInfos.Any()) { queryable.SqlBuilder.QueryBuilder.JoinQueryInfos.Last().EntityType = types.Last(); } queryable.SqlBuilder.QueryBuilder.TableShortName = shortName; queryable.SqlBuilder.QueryBuilder.JoinExpression = joinExpression; if (paramters != null) { queryable.SqlBuilder.QueryBuilder.Parameters.AddRange(paramters); } } protected void CreateEasyQueryJoin(Expression joinExpression, Type[] types, ISugarQueryable queryable) { this.SugarActionType = SugarActionType.Query; this.CreateQueryable(queryable); string shortName = string.Empty; queryable.SqlBuilder.QueryBuilder.EasyJoinInfos = this.GetEasyJoinInfo(joinExpression, ref shortName, queryable.SqlBuilder, types); queryable.SqlBuilder.QueryBuilder.TableShortName = shortName; queryable.SqlBuilder.QueryBuilder.JoinExpression = joinExpression; var isNoPgAuto = this.Context.CurrentConnectionConfig.MoreSettings?.PgSqlIsAutoToLower == false; if (isNoPgAuto) queryable.SqlBuilder.QueryBuilder.TableShortName = queryable.SqlBuilder.GetTranslationColumnName(shortName); } #endregion #region Private methods internal string GetN() { var N = "N"; if (_Context.CurrentConnectionConfig.MoreSettings != null && _Context.CurrentConnectionConfig.MoreSettings.DisableNvarchar) { N = ""; } return N; } internal bool IsVarchar() { if (_Context.CurrentConnectionConfig.MoreSettings != null && _Context.CurrentConnectionConfig.MoreSettings.DisableNvarchar) { return true; } return false; } private static void CheckDbDependency(ConnectionConfig config) { switch (config.DbType) { case DbType.MySql: DependencyManagement.TryMySqlData(); break; case DbType.SqlServer: break; case DbType.Sqlite: DependencyManagement.TrySqlite(); break; case DbType.Oracle: DependencyManagement.TryOracle(); break; case DbType.PostgreSQL: DependencyManagement.TryPostgreSQL(); break; case DbType.OpenGauss: Check.ExceptionEasy("Use DbType.PostgreSQL , ConnectionString add No Reset On Close=true", "OpenGausso数据库请使用DbType.PostgreSQL 并且连接字符串加上 No Reset On Close=true"); break; case DbType.HG: Check.ExceptionEasy("Use DbType.PostgreSQL", "瀚高数据库请使用DbType.PostgreSQL"); break; case DbType.Kdbndp: DependencyManagement.TryKdbndb(); break; case DbType.Dm: DependencyManagement.TryDm(); break; case DbType.Oscar: DependencyManagement.TryOscar(); break; case DbType.MySqlConnector: InstanceFactory.CustomDllName = SugarCompatible.IsFramework?"SqlSugar.MySqlConnector": "SqlSugar.MySqlConnectorCore"; break; case DbType.Access: InstanceFactory.CustomDllName = SugarCompatible.IsFramework?"SqlSugar.Access": "SqlSugar.AccessCore"; break; case DbType.Custom: Check.Exception(InstanceFactory.CustomDbName.IsNullOrEmpty() , "DbType.Custom: InstanceFactory.CustomDbName is not null "); Check.Exception(InstanceFactory.CustomNamespace.IsNullOrEmpty(), "DbType.Custom: InstanceFactory.CustomNamespace is not null "); Check.Exception(InstanceFactory.CustomDllName.IsNullOrEmpty(), "DbType.Custom: InstanceFactory.CustomDllName is not null "); break; case DbType.QuestDB: DependencyManagement.TryPostgreSQL(); break; case DbType.ClickHouse: Check.Exception(SugarCompatible.IsFramework, "ClickHouse only support .net core"); InstanceFactory.CustomDllName = SugarCompatible.IsFramework ? "SqlSugar.ClickHouse" : "SqlSugar.ClickHouseCore"; break; case DbType.GBase: Check.Exception(SugarCompatible.IsFramework, "GBase only support .net core"); InstanceFactory.CustomDllName = SugarCompatible.IsFramework ? "SqlSugar.GBase" : "SqlSugar.GBaseCore"; break; case DbType.Odbc: InstanceFactory.CustomDllName = SugarCompatible.IsFramework ? "SqlSugar.Odbc" : "SqlSugar.OdbcCore"; break; default: throw new Exception("ConnectionConfig.DbType is null"); } } protected List GetJoinInfos(ISqlBuilder sqlBuilder, Expression joinExpression, ref List parameters, ref string shortName, params Type[] entityTypeArray) { List result = new List(); var lambdaParameters = ((LambdaExpression)joinExpression).Parameters.ToList(); ILambdaExpressions expressionContext = sqlBuilder.QueryBuilder.LambdaExpressions; expressionContext.MappingColumns = this.MappingColumns; expressionContext.MappingTables = this.MappingTables; expressionContext.IsSingle = false; if (this.Context.CurrentConnectionConfig.MoreSettings != null) { expressionContext.PgSqlIsAutoToLower = this.Context.CurrentConnectionConfig.MoreSettings.PgSqlIsAutoToLower; } else { expressionContext.PgSqlIsAutoToLower = true; } if (this.Context.CurrentConnectionConfig.ConfigureExternalServices != null) expressionContext.SqlFuncServices = this.Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices; expressionContext.Resolve(joinExpression, ResolveExpressType.Join); int i = 0; var joinArray = MergeJoinArray(expressionContext.Result.GetResultArray()); if (joinArray == null) return null; parameters = expressionContext.Parameters; foreach (var entityType in entityTypeArray) { var isFirst = i == 0; ++i; JoinQueryInfo joinInfo = new JoinQueryInfo(); var hasMappingTable = expressionContext.MappingTables.HasValue(); MappingTable mappingInfo = null; if (hasMappingTable) { mappingInfo = expressionContext.MappingTables.FirstOrDefault(it => it.EntityName.Equals(entityType.Name, StringComparison.CurrentCultureIgnoreCase)); joinInfo.TableName = mappingInfo != null ? mappingInfo.DbTableName : entityType.Name; } else { joinInfo.TableName = entityType.Name; } var isNoPgAuto = this.Context.CurrentConnectionConfig.MoreSettings?.PgSqlIsAutoToLower == false; if (isFirst) { var firstItem = lambdaParameters.First(); lambdaParameters.Remove(firstItem); shortName = firstItem.Name; if (isNoPgAuto) shortName = sqlBuilder.GetTranslationColumnName(shortName); } var joinString = joinArray[i * 2 - 2]; joinInfo.ShortName = lambdaParameters[i - 1].Name; joinInfo.JoinType = (JoinType)Enum.Parse(typeof(JoinType), joinString); joinInfo.JoinWhere = joinArray[i * 2 - 1]; joinInfo.JoinIndex = i; joinInfo.EntityType = entityType; if (isNoPgAuto) joinInfo.ShortName = sqlBuilder.GetTranslationColumnName(joinInfo.ShortName); result.Add((joinInfo)); } expressionContext.Clear(); return result; } private string[] MergeJoinArray(string[] joinArray) { List result = new List(); string joinValue = null; int i = 0; if (joinArray == null) return null; foreach (var item in joinArray) { ++i; var isLast = joinArray.Length == i; var isJoinType = item.IsIn(JoinType.Full.ToString(),JoinType.Inner.ToString(), JoinType.Left.ToString(), JoinType.Right.ToString()); if (isJoinType) { if (joinValue != null) result.Add(joinValue); joinValue = null; result.Add(item); } else { isJoinType = false; joinValue += joinValue == null ? item : ("," + item); } if (isLast) { result.Add(joinValue); } } return result.ToArray(); ; } protected Dictionary GetEasyJoinInfo(Expression joinExpression, ref string shortName, ISqlBuilder builder, params Type[] entityTypeArray) { Dictionary result = new Dictionary(); var lambdaParameters = ((LambdaExpression)joinExpression).Parameters.ToList(); shortName = lambdaParameters.First().Name; var isNoPgAuto = this.Context.CurrentConnectionConfig.MoreSettings?.PgSqlIsAutoToLower == false; var index = 1; foreach (var item in entityTypeArray) { if (isNoPgAuto) { result.Add(UtilConstants.Space +builder.GetTranslationColumnName(lambdaParameters[index].Name), item.Name); } else { result.Add(UtilConstants.Space + lambdaParameters[index].Name, item.Name); } ++index; } return result; } #endregion } }