From 8b8b7f61271a46dba5eed3becf6dc52cb0f4074a Mon Sep 17 00:00:00 2001 From: sunkaixuan <610262374@qq.com> Date: Tue, 3 Jun 2025 20:03:23 +0800 Subject: [PATCH] Synchronous code --- .../Abstract/AdoProvider/AdoProvider.cs | 6 +- .../Abstract/DbMaintenanceProvider/Methods.cs | 2 +- .../FastestProvider/FastestProvider.cs | 4 + .../Abstract/FastestProvider/Private.cs | 4 + .../QueryableProvider/Entities/SqlInfo.cs | 1 + .../QueryableProvider/NavigatManager.cs | 19 ++++ .../QueryableProvider/QueryableProvider.cs | 1 + .../SqlBuilderProvider/QueryBuilder.cs | 1 + .../SqlBuilderProvider_Condition.cs | 1 + .../SqlSugar/Entities/DbFastestProperties.cs | 2 + .../ExpressionsToSql/Common/ExpressionTool.cs | 26 ++++++ .../Common/MethodCallExpressionModel.cs | 1 + .../DbMethods/DefaultDbMethod.cs | 33 +++++++ .../ExpressionsToSql/DbMethods/IDbMethods.cs | 1 + .../ExpressionsToSql/DbMethods/SqlFunc.cs | 5 +- .../ResolveItems/BaseResolve_Item.cs | 34 ++++++- .../MethodCallExpressionResolve_Helper.cs | 18 +++- .../ResolveItems/NewExpressionResolve.cs | 13 +++ .../OneToManyNavgateExpressionN.cs | 8 +- .../Subquery/Items/SubTake.cs | 93 +++++++++++++++++++ .../ExpressionsToSql/Subquery/SubResolve.cs | 4 + .../ExpressionsToSql/Subquery/SubTools.cs | 3 +- .../ExpressionsToSql/Subquery/Subquerable.cs | 5 + .../Subquery/SubqueryableN.cs | 33 +++++++ .../SqlSugar/Infrastructure/ContextMethods.cs | 17 +++- Src/Asp.Net/SqlSugar/Interface/IAdo.cs | 1 + Src/Asp.Net/SqlSugar/SqlSugar.csproj | 1 + Src/Asp.Net/SqlSugar/Utilities/UtilMethods.cs | 57 +++++++++++- 28 files changed, 378 insertions(+), 16 deletions(-) create mode 100644 Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubTake.cs diff --git a/Src/Asp.Net/SqlSugar/Abstract/AdoProvider/AdoProvider.cs b/Src/Asp.Net/SqlSugar/Abstract/AdoProvider/AdoProvider.cs index 414c4f617..a74580adb 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/AdoProvider/AdoProvider.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/AdoProvider/AdoProvider.cs @@ -46,7 +46,8 @@ namespace SqlSugar /// /// Add, delete and modify: the number of affected items; /// - public int SqlExecuteCount { get; private set; } = 0; + public int SqlExecuteCount { get; protected set; } = 0; + public SugarActionType SqlExecuteType { get=> this.Context.SugarActionType;} public StackTraceInfo SqlStackTrace { get { return UtilMethods.GetStackTrace(); } } public bool IsDisableMasterSlaveSeparation { get; set; } internal DateTime BeforeTime = DateTime.MinValue; @@ -1726,6 +1727,9 @@ namespace SqlSugar } protected void InitParameters(ref string sql, SugarParameter[] parameters) { + this.SqlExecuteCount = 0; + this.BeforeTime = DateTime.MinValue; + this.AfterTime = DateTime.MinValue; if (parameters.HasValue()) { foreach (var item in parameters) diff --git a/Src/Asp.Net/SqlSugar/Abstract/DbMaintenanceProvider/Methods.cs b/Src/Asp.Net/SqlSugar/Abstract/DbMaintenanceProvider/Methods.cs index 4239e0051..b8e103634 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/DbMaintenanceProvider/Methods.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/DbMaintenanceProvider/Methods.cs @@ -246,7 +246,7 @@ namespace SqlSugar { indexName = this.SqlBuilder.GetNoTranslationColumnName(indexName); tableName= this.SqlBuilder.GetNoTranslationColumnName(tableName); - this.Context.Ado.ExecuteCommand($" DROP INDEX {indexName} ON {tableName}"); + this.Context.Ado.ExecuteCommand($" DROP INDEX {indexName} "); return true; } public virtual bool DropView(string viewName) diff --git a/Src/Asp.Net/SqlSugar/Abstract/FastestProvider/FastestProvider.cs b/Src/Asp.Net/SqlSugar/Abstract/FastestProvider/FastestProvider.cs index 4ed1956f3..88c896f19 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/FastestProvider/FastestProvider.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/FastestProvider/FastestProvider.cs @@ -61,6 +61,10 @@ namespace SqlSugar { if (Size > 0) { + if (this.GetBuider()?.DbFastestProperties?.NoPage == true) + { + Size = int.MaxValue; + } int resul=0; await this.context.Utilities.PageEachAsync(datas, Size, async item => { diff --git a/Src/Asp.Net/SqlSugar/Abstract/FastestProvider/Private.cs b/Src/Asp.Net/SqlSugar/Abstract/FastestProvider/Private.cs index c52e394df..d8fdfe960 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/FastestProvider/Private.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/FastestProvider/Private.cs @@ -226,6 +226,10 @@ namespace SqlSugar private DataTable GetCopyWriteDataTable(DataTable dt) { var builder = GetBuider(); + if (builder.DbFastestProperties?.IsConvertDateTimeOffsetToDateTime == true) + { + dt = UtilMethods.ConvertDateTimeOffsetToDateTime(dt); + } if (builder.DbFastestProperties?.IsNoCopyDataTable == true) { return dt; diff --git a/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/Entities/SqlInfo.cs b/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/Entities/SqlInfo.cs index 09c6d6f88..94e67733d 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/Entities/SqlInfo.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/Entities/SqlInfo.cs @@ -9,6 +9,7 @@ namespace SqlSugar internal class SqlInfo { + public bool IsSelectNav { get; set; } public int? Take { get; set; } public int? Skip { get; set; } public string WhereString { get; set; } diff --git a/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/NavigatManager.cs b/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/NavigatManager.cs index 4ffc96486..367c6a7d5 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/NavigatManager.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/NavigatManager.cs @@ -856,6 +856,18 @@ namespace SqlSugar { var pkInfo = entityInfo.Columns.FirstOrDefault(x => x.IsPrimarykey); result.SelectString = (" " + queryable.QueryBuilder.GetExpressionValue(exp, ResolveExpressType.SelectSingle).GetString()); + if (ExpressionTool.ContainsTwoLevelAccess(exp)) + { + var shortName = ExpressionTool.GetParameters(exp).FirstOrDefault()?.Name; + if (shortName.HasValue()) + { + if (result.TableShortName == null) + { + result.TableShortName = shortName; + result.IsSelectNav = true; + } + } + } if (pkInfo != null) { var pkName = pkInfo.DbColumnName; @@ -941,6 +953,13 @@ namespace SqlSugar private static void AppColumns(SqlInfo result, ISugarQueryable queryable, string columnName) { var selectPkName = queryable.SqlBuilder.GetTranslationColumnName(columnName); + if (result.IsSelectNav) + { + if (result.SelectString != null && !result.SelectString.ToLower().Contains($" {selectPkName.ToLower()} AS {selectPkName.ToLower()}")) + { + result.SelectString = result.SelectString + "," + (selectPkName + " AS " + selectPkName); + } + } if (result.SelectString!=null && !result.SelectString.ToLower().Contains(selectPkName.ToLower())) { result.SelectString = result.SelectString + "," + (selectPkName +" AS "+ selectPkName); diff --git a/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs b/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs index f9fb99596..887883a7e 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs @@ -1781,6 +1781,7 @@ namespace SqlSugar var unionall = this.Context._UnionAll(tableQueryables.ToArray()); unionall.QueryBuilder.Includes = this.QueryBuilder.Includes; unionall.QueryBuilder.EntityType = typeof(T); + unionall.QueryBuilder.IsDisableMasterSlaveSeparation = this.QueryBuilder.IsDisableMasterSlaveSeparation; unionall.QueryBuilder.IsDisabledGobalFilter = this.QueryBuilder.IsDisabledGobalFilter; if (unionall.QueryBuilder.Includes?.Any()==true) { diff --git a/Src/Asp.Net/SqlSugar/Abstract/SqlBuilderProvider/QueryBuilder.cs b/Src/Asp.Net/SqlSugar/Abstract/SqlBuilderProvider/QueryBuilder.cs index 7b369ab80..5c5dea0f0 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/SqlBuilderProvider/QueryBuilder.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/SqlBuilderProvider/QueryBuilder.cs @@ -1109,6 +1109,7 @@ namespace SqlSugar public virtual bool IsSelectNoAll { get; set; } = false; public List AutoAppendedColumns { get; set; } public Dictionary MappingKeys { get; set; } + public List> SelectNewIgnoreColumns { get; set; } #endregion private string GetTableName(string entityName) diff --git a/Src/Asp.Net/SqlSugar/Abstract/SqlBuilderProvider/SqlBuilderProvider_Condition.cs b/Src/Asp.Net/SqlSugar/Abstract/SqlBuilderProvider/SqlBuilderProvider_Condition.cs index 629dccb6b..6eabcd58f 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/SqlBuilderProvider/SqlBuilderProvider_Condition.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/SqlBuilderProvider/SqlBuilderProvider_Condition.cs @@ -177,6 +177,7 @@ namespace SqlSugar builder.Replace(" ( AND ", " ( "); builder.Replace(" ( OR ", " ( "); builder.Replace(" OR AND ", " OR "); + builder.Replace(" AND AND ", " AND "); } } parameters.AddRange(childSqlInfo.Value); diff --git a/Src/Asp.Net/SqlSugar/Entities/DbFastestProperties.cs b/Src/Asp.Net/SqlSugar/Entities/DbFastestProperties.cs index 1aa38e3d7..d557185b4 100644 --- a/Src/Asp.Net/SqlSugar/Entities/DbFastestProperties.cs +++ b/Src/Asp.Net/SqlSugar/Entities/DbFastestProperties.cs @@ -13,5 +13,7 @@ namespace SqlSugar public bool IsOffIdentity { get; set; } public bool IsMerge { get; set; } public bool IsNoCopyDataTable { get; set; } + public bool IsConvertDateTimeOffsetToDateTime { get; set; } + public bool NoPage { get; set; } } } diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/ExpressionTool.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/ExpressionTool.cs index d87bd70f9..4904a8522 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/ExpressionTool.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/ExpressionTool.cs @@ -10,6 +10,32 @@ namespace SqlSugar { public class ExpressionTool { + public static bool ContainsTwoLevelAccess(Expression exp) + { + var result = false; + + if (exp is LambdaExpression lambda && + lambda.Body is MemberInitExpression initExpr) + { + var param = lambda.Parameters[0]; + + foreach (var binding in initExpr.Bindings) + { + if (binding is MemberAssignment assign) + { + if (assign.Expression is MemberExpression outer && + outer.Expression is MemberExpression inner && + inner.Expression == param) + { + result = true; + break; // 已经找到了,就退出循环 + } + } + } + } + + return result; + } public static string GetMemberNameByMethod(Expression expression, string name) { diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/MethodCallExpressionModel.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/MethodCallExpressionModel.cs index 093b4d39a..7f544439e 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/MethodCallExpressionModel.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Common/MethodCallExpressionModel.cs @@ -11,6 +11,7 @@ namespace SqlSugar public List Args { get; set; } public string Name { get; set; } public dynamic Data { get; set; } + public object DataObject { get; set; } public Expression Expression { get; set; } public Expression BaseExpression { get; set; } public List Parameters { get; set; } diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/DefaultDbMethod.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/DefaultDbMethod.cs index a9c49626c..e95f087c6 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/DefaultDbMethod.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/DefaultDbMethod.cs @@ -946,6 +946,20 @@ namespace SqlSugar newValue = value.ToSqlValue(); } } + if (columnInfo.UnderType == UtilConstants.StringType&& model.Conext?.SugarContext?.Context?.CurrentConnectionConfig?.DbType==DbType.SqlServer) + { + if (model.Conext?.SugarContext?.Context?.CurrentConnectionConfig?.MoreSettings?.DisableNvarchar != true) + { + if (columnInfo.SqlParameterDbType is System.Data.DbType type && type == System.Data.DbType.AnsiString) + { + + } + else + { + newValue = "N" + newValue; + } + } + } sql = sql.Replace(replace, newValue); } } @@ -1111,6 +1125,20 @@ namespace SqlSugar else { newValue = value.ToSqlValue(); + if (columnInfo.EntityName == "String" && model.Conext?.SugarContext?.Context?.CurrentConnectionConfig?.DbType == DbType.SqlServer) + { + if (model.Conext?.SugarContext?.Context?.CurrentConnectionConfig?.MoreSettings?.DisableNvarchar != true) + { + if (model.DataObject is EntityColumnInfo dc&& dc.SqlParameterDbType is System.Data.DbType type && type == System.Data.DbType.AnsiString) + { + + } + else + { + newValue = "N" + newValue; + } + } + } } } //Regex regex = new Regex("\@"); @@ -1363,5 +1391,10 @@ namespace SqlSugar { return string.Join(",", model.Args.Select(it => it.MemberName)); } + public virtual string UNIX_TIMESTAMP(MethodCallExpressionModel model) + { + var parameterNameA = model.Args[0].MemberName; + return $" UNIX_TIMESTAMP({parameterNameA}) "; + } } } diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/IDbMethods.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/IDbMethods.cs index aeb0578a2..9da948fb0 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/IDbMethods.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/IDbMethods.cs @@ -131,5 +131,6 @@ namespace SqlSugar string PgsqlArrayContains(MethodCallExpressionModel model); string SelectFields(MethodCallExpressionModel model); string Coalesce(MethodCallExpressionModel model); + string UNIX_TIMESTAMP(MethodCallExpressionModel model); } } diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/SqlFunc.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/SqlFunc.cs index 8f2b95b76..dcacc02d6 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/SqlFunc.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/SqlFunc.cs @@ -10,7 +10,10 @@ namespace SqlSugar { public partial class SqlFunc { - + public static long UNIX_TIMESTAMP(DateTime dateTime) + { + throw new NotSupportedException("Can only be used in expressions"); + } public static T Coalesce(T value1, T value2) { throw new NotSupportedException("Can only be used in expressions"); diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/BaseResolve_Item.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/BaseResolve_Item.cs index b759913a1..977878736 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/BaseResolve_Item.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/BaseResolve_Item.cs @@ -84,7 +84,13 @@ namespace SqlSugar this.Context.SingleTableNameSubqueryShortName = ps.FirstOrDefault().Name; return; } - else if (item is MethodCallExpression&&ExpressionTool.IsVariable(item)) + else if (item is MethodCallExpression && ExpressionTool.IsVariable(item)) + { + var p = GetNewExpressionValue(item); + parameter.Context.Result.Append(this.Context.GetAsString2(asName, p)); + return; + } + else if (item is ConditionalExpression&& ExpressionTool.GetParameters(item).Count > 0) { var p = GetNewExpressionValue(item); parameter.Context.Result.Append(this.Context.GetAsString2(asName, p)); @@ -183,11 +189,35 @@ namespace SqlSugar if (item is MemberInitExpression) { newExpressionInfos = ExpressionTool.GetNewexpressionInfos(item, this.Context, this); + var ignorePropertyNames = item.Type.GetProperties().Where(it => it.PropertyType.IsClass()&&!it.PropertyType.Name.StartsWith("System.")) + .Select(it=>it.PropertyType.Name).ToList(); + if (ignorePropertyNames.Count > 0) + { + var names = new List() { }; + foreach (MemberBinding binding in ((MemberInitExpression)item).Bindings) + { + names.Add(binding.Member.Name); + } + ignorePropertyNames = ignorePropertyNames.Where(it => !names.Contains(it)).ToList(); + var q=this.Context?.SugarContext?.QueryBuilder; + if (q != null) + { + foreach (var ignorePropertyName in ignorePropertyNames) + { + if (q.SelectNewIgnoreColumns == null) + { + q.SelectNewIgnoreColumns = new List>(); + } + var addItem = new KeyValuePair(ignorePropertyName,item.Type.Name); + q.SelectNewIgnoreColumns.Add(addItem); + } + } + } } else { newExpressionInfos = ExpressionTool.GetNewDynamicexpressionInfos(item, this.Context, this); - } + } foreach (NewExpressionInfo newExpressionInfo in newExpressionInfos) { //var property=item.Type.GetProperties().Where(it => it.Name == newExpressionInfo.l).First(); diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve_Helper.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve_Helper.cs index 15ca4e865..a14ace2fb 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve_Helper.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve_Helper.cs @@ -298,16 +298,32 @@ namespace SqlSugar var lamExp = (item as LambdaExpression); var pExp = lamExp.Parameters[0]; var pname = pExp.Name; + var columns = this.Context.SugarContext.Context.EntityMaintenance.GetEntityInfo(pExp.Type).Columns; + if (columns.Count==0&&pExp.Type.IsValueType && pExp.Type != typeof(string)) + { + columns = new List() { new EntityColumnInfo() { UnderType=UtilMethods.GetUnderType( pExp.Type) ,PropertyName=pExp.Type.Name,DbTableName= pExp.Type.Name } }; + } model.Args.Add(new MethodCallExpressionArgs() { MemberValue = new ListAnyParameter() { Sql = sql, Name = pname, - Columns = this.Context.SugarContext.Context.EntityMaintenance.GetEntityInfo(pExp.Type).Columns, + Columns = columns, ConvetColumnFunc = this.Context.GetTranslationColumnName } }); + if (lamExp.Body is MethodCallExpression callExpression) + { + var callObject = callExpression.Object; + + if (callObject is MemberExpression memberExpression && memberExpression?.Expression is ParameterExpression parameterExpression) + { + var entity = this.Context.SugarContext.Context.EntityMaintenance.GetEntityInfo(parameterExpression.Type); + var columnInfo = entity.Columns.FirstOrDefault(it => it.PropertyName == memberExpression.Member.Name); + model.DataObject = columnInfo; + } + } if (this.Context.IsSingle && this.Context.SingleTableNameSubqueryShortName == null) { ParameterExpressionVisitor visitor = new ParameterExpressionVisitor(); diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/NewExpressionResolve.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/NewExpressionResolve.cs index dda7a9379..7df1ab879 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/NewExpressionResolve.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/NewExpressionResolve.cs @@ -158,6 +158,19 @@ namespace SqlSugar continue; } ++i; + if (item is ParameterExpression) + { + var itemType = item.Type; + var ignoreProperty = itemType.GetProperties().FirstOrDefault(it => it.PropertyType == itemType); + if (ignoreProperty!=null&& ignoreProperty.Name!=memberName) + { + if (this.Context.SugarContext.QueryBuilder.SelectNewIgnoreColumns == null) + { + this.Context.SugarContext.QueryBuilder.SelectNewIgnoreColumns = new List>(); + } + this.Context.SugarContext.QueryBuilder.SelectNewIgnoreColumns.Add(new KeyValuePair(ignoreProperty.Name, itemType.Name)); + } + } ResolveNewExpressions(parameter, item, memberName); } } diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/OneToManyNavgateExpressionN.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/OneToManyNavgateExpressionN.cs index e06ed5c8f..d57b05a5c 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/OneToManyNavgateExpressionN.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/OneToManyNavgateExpressionN.cs @@ -131,7 +131,7 @@ namespace SqlSugar Check.ExceptionEasy(FirstPkColumn == null, $"{ last.ThisEntityInfo.EntityName} need PrimayKey", $"使用导航属性{ last.ThisEntityInfo.EntityName} 缺少主键"); var PkColumn = last.ParentEntityInfo.Columns.FirstOrDefault(it => it.PropertyName == last.Nav.Name); Check.ExceptionEasy(PkColumn == null, $"{ last.ParentEntityInfo.EntityName} no found {last.Nav.Name}", $"{ last.ParentEntityInfo.EntityName} 不存在 {last.Nav.Name}"); - queryable.Where($" {this.shorName}.{ queryable.SqlBuilder.GetTranslationColumnName(PkColumn.DbColumnName)} = {masterShortName}.{queryable.SqlBuilder.GetTranslationColumnName(FirstPkColumn.DbColumnName)} "); + queryable.Where($" {queryable.SqlBuilder.GetTranslationColumnName(this.shorName)}.{ queryable.SqlBuilder.GetTranslationColumnName(PkColumn.DbColumnName)} = {queryable.SqlBuilder.GetTranslationColumnName(masterShortName)}.{queryable.SqlBuilder.GetTranslationColumnName(FirstPkColumn.DbColumnName)} "); queryable.WhereIF(this.whereSql.HasValue(), GetWhereSql1(this.whereSql,lastShortName, joinInfos, queryable.SqlBuilder)); MapperSql.Sql = $"( {queryable.ToSql().Key} ) "; if (isAny) @@ -176,7 +176,7 @@ namespace SqlSugar // navColum = item.ParentEntityInfo.Columns.FirstOrDefault(it => it.PropertyName == item.Nav.Name); //} Check.ExceptionEasy(pkColumn == null, $"{item.ThisEntityInfo.EntityName} need PrimayKey", $"使用导航属性{item.ThisEntityInfo.EntityName} 缺少主键"); - var on = $" {shortName}.{queryable.SqlBuilder.GetTranslationColumnName(pkColumn.DbColumnName)}={formInfo.ThisEntityInfo.DbTableName + (i - 1)}.{queryable.SqlBuilder.GetTranslationColumnName(navColum.DbColumnName)}"; + var on = $" {queryable.SqlBuilder.GetTranslationColumnName(shortName)}.{queryable.SqlBuilder.GetTranslationColumnName(pkColumn.DbColumnName)}={queryable.SqlBuilder.GetTranslationColumnName(formInfo.ThisEntityInfo.DbTableName + (i - 1))}.{queryable.SqlBuilder.GetTranslationColumnName(navColum.DbColumnName)}"; queryable.AddJoinInfo(item.ThisEntityInfo.DbTableName, shortName, on, JoinType.Inner); ++i; index++; @@ -270,13 +270,13 @@ namespace SqlSugar } this.whereSql =Regex.Replace(this.whereSql, regex, - lastShortName + "." + sqlBuilder.GetTranslationColumnName(it.DbColumnName)); + sqlBuilder.GetTranslationColumnName(lastShortName) + "." + sqlBuilder.GetTranslationColumnName(it.DbColumnName)); } else { var oldWhere = this.whereSql; var newWhere = this.whereSql.Replace(sqlBuilder.GetTranslationColumnName(it.DbColumnName), - lastShortName + "." + sqlBuilder.GetTranslationColumnName(it.DbColumnName)); + sqlBuilder.GetTranslationColumnName(lastShortName) + "." + sqlBuilder.GetTranslationColumnName(it.DbColumnName)); if (oldWhere != newWhere && !oldWhere.Contains($" {sqlBuilder.GetTranslationColumnName(it.DbColumnName)}")) { diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubTake.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubTake.cs new file mode 100644 index 000000000..2fe4755a8 --- /dev/null +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubTake.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubTake : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public ExpressionContext Context + { + get; set; + } + + public Expression Expression + { + get; set; + } + + public string Name + { + get + { + return "Take"; + } + } + + public int Sort + { + get + { + if (this.Context is SqlServerExpressionContext || this.Context.GetType().Name.Contains("Access")) + { + return 150; + } + else if (this.Context is OracleExpressionContext) + { + + return 401; + } + else + { + return 490; + } + } + } + + + public string GetValue(Expression expression) + { + var numExp = (expression as MethodCallExpression).Arguments[0]; + var num =1; + if (ExpressionTool.GetParameters(numExp).Any()) + { + var copyContext = this.Context.GetCopyContextWithMapping(); + copyContext.IsSingle = false; + copyContext.Resolve(numExp, ResolveExpressType.WhereMultiple); + copyContext.Result.GetString(); + } + else + { + num = ExpressionTool.DynamicInvoke(numExp).ObjToInt(); + } + var take = (expression as MethodCallExpression); + if (this.Context is SqlServerExpressionContext || this.Context.GetType().Name.Contains("Access")) + { + return "TOP " + num; + } + else if (this.Context is OracleExpressionContext) + { + return (HasWhere ? "AND" : "WHERE") + " ROWNUM<=" + num; + } + else if (this.Context is PostgreSQLExpressionContext || this.Context?.SugarContext?.Context?.CurrentConnectionConfig?.MoreSettings?.DatabaseModel == DbType.PostgreSQL) + { + return "limit " + num; + } + else if (this.Context.GetLimit() != null) + { + return this.Context.GetLimit(); + } + else + { + return "limit " + num; + } + } + } +} \ No newline at end of file diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubResolve.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubResolve.cs index 89e8eeef5..c9deae114 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubResolve.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubResolve.cs @@ -288,6 +288,10 @@ namespace SqlSugar { this.context.IsAsAttr = true; } + if (isubList.Any(it => it is SubSelect) && isubList.Any(it => it is SubTake)) + { + isubList.RemoveAll(it => it is SubTake); + } List result = isubList.Select(it => { it.HasWhere = isHasWhere; diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubTools.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubTools.cs index 3fc66cb48..fd2126a8d 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubTools.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubTools.cs @@ -40,7 +40,8 @@ namespace SqlSugar new SubDistinctCount{ Context=Context }, new SubToList{ Context=Context}, new SubFirst(){ Context=Context }, - new SubAsWithAttr(){ Context=Context } + new SubAsWithAttr(){ Context=Context }, + new SubTake(){ Context=Context } }; } diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Subquerable.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Subquerable.cs index a84a930c7..7302b2c7a 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Subquerable.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Subquerable.cs @@ -224,5 +224,10 @@ namespace SqlSugar { return this; } + + public Subqueryable Take(int takeNum) + { + return this; + } } } diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubqueryableN.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubqueryableN.cs index d22490899..dc99b8295 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubqueryableN.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubqueryableN.cs @@ -68,6 +68,10 @@ namespace SqlSugar public List ToList(Func selector) { return null; + } + public new Subqueryable Take(int takeNum) + { + return this; } } public class Subqueryable : Subqueryable where T1 : class, new() @@ -127,6 +131,10 @@ namespace SqlSugar public List ToList(Func selector) { return null; + } + public new Subqueryable Take(int takeNum) + { + return this; } } public class Subqueryable : Subqueryable where T1 : class, new() @@ -182,6 +190,10 @@ namespace SqlSugar public List ToList(Func selector) { return null; + } + public new Subqueryable Take(int takeNum) + { + return this; } } public class Subqueryable : Subqueryable where T1 : class, new() @@ -242,6 +254,10 @@ namespace SqlSugar public List ToList(Func selector) { return null; + } + public new Subqueryable Take(int takeNum) + { + return this; } } public class Subqueryable : Subqueryable where T1 : class, new() @@ -298,6 +314,10 @@ namespace SqlSugar public List ToList(Func selector) { return null; + } + public new Subqueryable Take(int takeNum) + { + return this; } } public class Subqueryable : Subqueryable where T1 : class, new() @@ -415,6 +435,11 @@ namespace SqlSugar { return default(TResult); } + + public new Subqueryable Take(int takeNum) + { + return this; + } } public class Subqueryable : Subqueryable where T1 : class, new() { @@ -543,6 +568,10 @@ namespace SqlSugar { return default(TResult); } + public new Subqueryable Take(int takeNum) + { + return this; + } } public class Subqueryable : Subqueryable where T1 : class, new() { @@ -663,5 +692,9 @@ namespace SqlSugar { return default(TResult); } + public new Subqueryable Take(int takeNum) + { + return this; + } } } diff --git a/Src/Asp.Net/SqlSugar/Infrastructure/ContextMethods.cs b/Src/Asp.Net/SqlSugar/Infrastructure/ContextMethods.cs index 12bd4917a..6e835e46d 100644 --- a/Src/Asp.Net/SqlSugar/Infrastructure/ContextMethods.cs +++ b/Src/Asp.Net/SqlSugar/Infrastructure/ContextMethods.cs @@ -507,7 +507,16 @@ namespace SqlSugar } else { - result.Add(name, DataReaderToDynamicList_Part(readerValues, item, reval, mappingKeys)); + List ignorePropertyNames = null; + if (this.QueryBuilder?.SelectNewIgnoreColumns?.Any() == true) + { + var ignoreColumns= this.QueryBuilder.SelectNewIgnoreColumns.Where(it => it.Value == item.PropertyType.Name).ToList(); + if (ignoreColumns.Any()) + { + ignorePropertyNames = ignoreColumns.Select(it => it.Key).ToList(); + } + } + result.Add(name, DataReaderToDynamicList_Part(readerValues, item, reval, mappingKeys, ignorePropertyNames)); } } else @@ -645,7 +654,7 @@ namespace SqlSugar Regex.IsMatch(readerValues.First(y => y.Key.EqualCase(item.Name)).Value.ToString(), @"^\[{.+\}]$"); } - private Dictionary DataReaderToDynamicList_Part(Dictionary readerValues, PropertyInfo item, List reval, Dictionary mappingKeys = null) + private Dictionary DataReaderToDynamicList_Part(Dictionary readerValues, PropertyInfo item, List reval, Dictionary mappingKeys = null,List ignoreColumns=null) { Dictionary result = new Dictionary(); var type = item.PropertyType; @@ -673,6 +682,10 @@ namespace SqlSugar var typeName = type.Name; if (prop.PropertyType.IsClass()) { + if (ignoreColumns?.Contains(name) == true) + { + continue; + } var suagrColumn = prop.GetCustomAttribute(); if (suagrColumn != null && suagrColumn.IsJson) { diff --git a/Src/Asp.Net/SqlSugar/Interface/IAdo.cs b/Src/Asp.Net/SqlSugar/Interface/IAdo.cs index 77bd5b5cc..2716e16fb 100644 --- a/Src/Asp.Net/SqlSugar/Interface/IAdo.cs +++ b/Src/Asp.Net/SqlSugar/Interface/IAdo.cs @@ -37,6 +37,7 @@ namespace SqlSugar TimeSpan SqlExecutionTime { get; } TimeSpan ConnectionExecutionTime { get; } int SqlExecuteCount { get; } + SugarActionType SqlExecuteType { get;} IDbBind DbBind { get; } void SetCommandToAdapter(IDataAdapter adapter, DbCommand command); IDataAdapter GetAdapter(); diff --git a/Src/Asp.Net/SqlSugar/SqlSugar.csproj b/Src/Asp.Net/SqlSugar/SqlSugar.csproj index c1ccda412..dee2c67ca 100644 --- a/Src/Asp.Net/SqlSugar/SqlSugar.csproj +++ b/Src/Asp.Net/SqlSugar/SqlSugar.csproj @@ -192,6 +192,7 @@ + diff --git a/Src/Asp.Net/SqlSugar/Utilities/UtilMethods.cs b/Src/Asp.Net/SqlSugar/Utilities/UtilMethods.cs index d3287098e..84d07e475 100644 --- a/Src/Asp.Net/SqlSugar/Utilities/UtilMethods.cs +++ b/Src/Asp.Net/SqlSugar/Utilities/UtilMethods.cs @@ -18,6 +18,49 @@ namespace SqlSugar { public class UtilMethods { + public static DataTable ConvertDateTimeOffsetToDateTime(DataTable table) + { + if (!table.Columns.Cast().Any(it => it.DataType == typeof(DateTimeOffset))) + { + return table; + } + DataTable newTable = table.Clone(); + newTable.TableName = table.TableName; + // 替换所有 DateTimeOffset 列为 DateTime + foreach (DataColumn column in newTable.Columns) + { + if (column.DataType == typeof(DateTimeOffset)) + { + column.DataType = typeof(DateTime); // 会报错,不能直接改 + } + } + + // 需要重新构建新表结构 + DataTable finalTable = new DataTable(); + finalTable.TableName = table.TableName; + foreach (DataColumn column in table.Columns) + { + Type newType = column.DataType == typeof(DateTimeOffset) ? typeof(DateTime) : column.DataType; + finalTable.Columns.Add(column.ColumnName, newType); + } + + // 拷贝并转换数据 + foreach (DataRow row in table.Rows) + { + DataRow newRow = finalTable.NewRow(); + foreach (DataColumn column in table.Columns) + { + var value = row[column]; + if (value is DateTimeOffset dto) + newRow[column.ColumnName] = dto.DateTime; + else + newRow[column.ColumnName] = value; + } + finalTable.Rows.Add(newRow); + } + + return finalTable; + } public static string EscapeLikeValue(ISqlSugarClient db, string value, char wildcard='%') { var dbType = db.CurrentConnectionConfig.DbType; @@ -38,8 +81,16 @@ namespace SqlSugar case DbType.Odbc: case DbType.TDSQLForPGODBC: // SQL Server 使用中括号转义 %, _ 等 - value = value.Replace("[", "[[]") - .Replace("]", "[]]") + var keyLeft = "[[]"; + var keyRight = "[]]"; + var leftGuid = Guid.NewGuid().ToString(); + var rightGuid = Guid.NewGuid().ToString(); + value = value.Replace("[", leftGuid) + .Replace("]", rightGuid); + + value = value.Replace(leftGuid, keyLeft) + .Replace(rightGuid, keyRight); + value =value .Replace(wildcardStr, $"[{wildcard}]"); break; @@ -1743,7 +1794,7 @@ namespace SqlSugar } else { - result = result.Replace(item.ParameterName, $"N'{item.Value.ObjToString().Replace("@", guid).ToSqlFilter()}'"); + result = result.Replace(item.ParameterName, $"N'{item.Value.ObjToStringNoTrim().Replace("@", guid).ToSqlFilter()}'"); } } }