diff --git a/Src/Asp.Net/SqlServerTest/Demos/1_Query.cs b/Src/Asp.Net/SqlServerTest/Demos/1_Query.cs index 308619a4a..3c6e96e86 100644 --- a/Src/Asp.Net/SqlServerTest/Demos/1_Query.cs +++ b/Src/Asp.Net/SqlServerTest/Demos/1_Query.cs @@ -184,6 +184,9 @@ namespace OrmTest.Demo public static void Easy() { var db = GetInstance(); + var getAll2 = db.Queryable() + .Where(it => it.Id == SqlFunc.Subqueryable().Where(s => s.Id == it.Id).Select(s => s.Id)) + .ToList(); var getAll = db.Queryable().ToList(); var getAllOrder = db.Queryable().OrderBy(it => it.Id).OrderBy(it => it.Name, OrderByType.Desc).ToList(); var getId = db.Queryable().Select(it => it.Id).ToList(); diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/DefaultDbMethod.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/DefaultDbMethod.cs index 7cc02e710..d6edde71e 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/DefaultDbMethod.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/DefaultDbMethod.cs @@ -295,6 +295,11 @@ namespace SqlSugar return string.Join("", strings); } + public virtual string Pack(string sql) + { + return "(" + sql + ")"; + } + public virtual string EqualTrue(string fieldName) { return "( " + fieldName + "=1 )"; diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/IDbMethods.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/IDbMethods.cs index 38c869497..1246de45f 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/IDbMethods.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/DbMethods/IDbMethods.cs @@ -24,6 +24,7 @@ namespace SqlSugar string DateIsSameDay(MethodCallExpressionModel model); string DateIsSameByType(MethodCallExpressionModel model); string DateAddByType(MethodCallExpressionModel model); + string DateValue(MethodCallExpressionModel model); string DateAddDay(MethodCallExpressionModel model); string Between(MethodCallExpressionModel model); @@ -53,6 +54,7 @@ namespace SqlSugar string GuidNew(); string MergeString(params string[] strings); string EqualTrue(string value); + string Pack(string sql); string Null(); } } diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs index d7c9e30f1..764971cf3 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs @@ -40,6 +40,13 @@ namespace SqlSugar this.Context.Result.Append(this.Context.DbMehtods.GuidNew()); return; } + else if (IsSubMethod(express, methodName)) + { + SubResolve subResolve = new SubResolve(express, this.Context); + var appendSql = subResolve.GetSql(); + base.AppendValue(parameter, isLeft, appendSql); + return; + } if (!isValidNativeMethod && express.Method.DeclaringType.Namespace.IsIn("System.Linq", "System.Collections.Generic") && methodName == "Contains") { methodName = "ContainsArray"; @@ -117,7 +124,8 @@ namespace SqlSugar { this.Context.ResolveType = ResolveExpressType.WhereSingle; } - else { + else + { this.Context.ResolveType = ResolveExpressType.WhereMultiple; } Where(parameter, isLeft, name, args, model); @@ -140,7 +148,7 @@ namespace SqlSugar model.Args.AddRange(appendArgs); } } - if (parameter.BaseParameter.BaseParameter.BaseParameter==null) + if (parameter.BaseParameter.BaseParameter.BaseParameter == null) { this.Context.Result.Append(GetMdthodValue(name, model)); } @@ -167,7 +175,7 @@ namespace SqlSugar { var isBinaryExpression = item is BinaryExpression || item is MethodCallExpression; var isConst = item is ConstantExpression; - var isIIF= name == "IIF"; + var isIIF = name == "IIF"; var isIFFBoolMember = isIIF && (item is MemberExpression) && (item as MemberExpression).Type == UtilConstants.BoolType; var isIFFUnary = isIIF && (item is UnaryExpression) && (item as UnaryExpression).Operand.Type == UtilConstants.BoolType; var isIFFBoolBinary = isIIF && (item is BinaryExpression) && (item as BinaryExpression).Type == UtilConstants.BoolType; @@ -198,7 +206,8 @@ namespace SqlSugar AppendModelByIIFBinary(parameter, model, item); } - else if (isIFFBoolMethod && !isFirst) { + else if (isIFFBoolMethod && !isFirst) + { AppendModelByIIFMethod(parameter, model, item); } else if (isBinaryExpression) @@ -251,7 +260,7 @@ namespace SqlSugar private void AppendModelByIIFMethod(ExpressionParameter parameter, MethodCallExpressionModel model, Expression item) { var methodExpression = item as MethodCallExpression; - if (methodExpression.Method.Name.IsIn("ToBool", "ToBoolean","IIF")) + if (methodExpression.Method.Name.IsIn("ToBool", "ToBoolean", "IIF")) { model.Args.Add(base.GetMethodCallArgs(parameter, item)); } @@ -433,6 +442,11 @@ namespace SqlSugar { "AddMilliseconds",DateType.Millisecond} }; + + private static bool IsSubMethod(MethodCallExpression express, string methodName) + { + return SubTool.SubItems.Any(it => it.Name == methodName) && express.Object != null && express.Object.Type.Name == "Subqueryable`1"; + } private void CheckMethod(MethodCallExpression expression) { Check.Exception(expression.Method.ReflectedType().FullName != ExpressionConst.SqlFuncFullName, string.Format(ErrorMessage.MethodError, expression.Method.Name)); diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/ISubAction.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/ISubAction.cs index 42aa2f828..60f885320 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/ISubAction.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/ISubAction.cs @@ -11,5 +11,6 @@ namespace SqlSugar string Name { get; } string GetValue(ExpressionContext context, Expression expression); int Sort { get; } + Expression Expression { get; set; } } } diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubAny.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubAny.cs index 6aa2f35fe..74132c483 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubAny.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubAny.cs @@ -8,6 +8,11 @@ namespace SqlSugar { public class SubAny : ISubOperation { + public Expression Expression + { + get;set; + } + public string Name { get diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubBegin'.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubBegin'.cs index 2b0d2aa65..18a04aefd 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubBegin'.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubBegin'.cs @@ -16,6 +16,11 @@ namespace SqlSugar } } + public Expression Expression + { + get; set; + } + public int Sort { get diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubFromTable.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubFromTable.cs index bfef1348b..162eae527 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubFromTable.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubFromTable.cs @@ -12,10 +12,15 @@ namespace SqlSugar { get { - throw new NotImplementedException(); + return "Subqueryable"; } } + public Expression Expression + { + get; set; + } + public int Sort { get @@ -23,9 +28,12 @@ namespace SqlSugar return 300; } } - public string GetValue(ExpressionContext context, Expression expression = null) + public string GetValue(ExpressionContext context, Expression expression) { - return context.GetTranslationTableName(expression.Type.Name, true); + var exp = expression as MethodCallExpression; + var resType = exp.Method.ReturnType; + var name = resType.GetGenericArguments().First().Name; + return "FROM "+context.GetTranslationTableName(name, true); } } } diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubSelect.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubSelect.cs index 38facb47c..a6c402e3e 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubSelect.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubSelect.cs @@ -16,6 +16,12 @@ namespace SqlSugar } } + public Expression Expression + { + get; set; + } + + public int Sort { get @@ -26,12 +32,8 @@ namespace SqlSugar public string GetValue(ExpressionContext context, Expression expression = null) { - var newContext=context.GetCopyContext(); - newContext.ParameterIndex = context.ParameterIndex; - newContext.Resolve(expression, ResolveExpressType.SelectMultiple); - context.Parameters.AddRange(newContext.Parameters); - context.ParameterIndex = newContext.ParameterIndex; - return newContext.Result.GetResultString(); + var exp = expression as MethodCallExpression; + return SubTool.GetMethodValue(context, exp.Arguments[0],ResolveExpressType.FieldSingle); } } } diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubWhere.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubWhere.cs index 393090e8e..c3de671ab 100644 --- a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubWhere.cs +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/Items/SubWhere.cs @@ -6,13 +6,18 @@ using System.Text; namespace SqlSugar.ExpressionsToSql.Subquery { - public class SubWhere : ISubOperation + public class SubWhere: ISubOperation { public string Name { get { return "Where"; } } + public Expression Expression + { + get; set; + } + public int Sort { get @@ -21,14 +26,10 @@ namespace SqlSugar.ExpressionsToSql.Subquery } } - public string GetValue(ExpressionContext context, Expression expression = null) + public string GetValue(ExpressionContext context, Expression expression) { - var newContext = context.GetCopyContext(); - newContext.ParameterIndex = context.ParameterIndex; - newContext.Resolve(expression, ResolveExpressType.WhereMultiple); - context.Parameters.AddRange(newContext.Parameters); - context.ParameterIndex = newContext.ParameterIndex; - return newContext.Result.GetResultString(); + var exp = expression as MethodCallExpression; + return "WHERE "+SubTool.GetMethodValue(context, exp.Arguments[0], ResolveExpressType.WhereMultiple); } } } diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubResolve.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubResolve.cs new file mode 100644 index 000000000..9c4b342b5 --- /dev/null +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubResolve.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubResolve + { + List allMethods = new List(); + private ExpressionContext context = null; + public SubResolve(MethodCallExpression expression, ExpressionContext context) + { + this.context = context; + var currentExpression = expression; + allMethods.Add(currentExpression); + while (currentExpression != null) + { + var addItem = currentExpression.Object as MethodCallExpression; + if (addItem != null) + allMethods.Add(addItem); + currentExpression = addItem; + } + } + + public string GetSql() + { + List subItems = GetSubItems(); + var sql = string.Join(UtilConstants.Space, subItems); + return this.context.DbMehtods.Pack(sql); + } + + private List GetSubItems() + { + var isubList = this.allMethods.Select(exp => + { + var methodName = exp.Method.Name; + var item = SubTool.SubItems.First(s => s.Name == methodName); + item.Expression = exp; + return item; + }) + .OrderBy(it => it.Sort).ToList(); + isubList.Insert(0, new SubBegin()); + List result = isubList.Select(it => + { + return it.GetValue(this.context, it.Expression); + }).ToList(); + return result; + } + } +} diff --git a/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubTool.cs b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubTool.cs new file mode 100644 index 000000000..c21e06b06 --- /dev/null +++ b/Src/Asp.Net/SqlSugar/ExpressionsToSql/Subquery/SubTool.cs @@ -0,0 +1,33 @@ +using SqlSugar.ExpressionsToSql.Subquery; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubTool + { + public static List SubItems = new List() + { + new SubSelect(), + new SubWhere(), + new SubAny(), + new SubBegin(), + new SubFromTable() + }; + + public static string GetMethodValue(ExpressionContext context,Expression item,ResolveExpressType type) + { + var newContext = context.GetCopyContext(); + newContext.MappingColumns = context.MappingColumns; + newContext.MappingTables = context.MappingTables; + newContext.IgnoreComumnList = context.IgnoreComumnList; + newContext.Resolve(item,type); + context.Index = newContext.Index; + context.ParameterIndex = newContext.ParameterIndex; + return newContext.Result.GetResultString(); + } + } +} diff --git a/Src/Asp.Net/SqlSugar/SqlSugar.csproj b/Src/Asp.Net/SqlSugar/SqlSugar.csproj index cd36de44b..2dd5ea5ee 100644 --- a/Src/Asp.Net/SqlSugar/SqlSugar.csproj +++ b/Src/Asp.Net/SqlSugar/SqlSugar.csproj @@ -79,6 +79,8 @@ + +