mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-11-04 17:20:49 +08:00 
			
		
		
		
	分组聚合查询
This commit is contained in:
		@@ -13,39 +13,44 @@ namespace FreeSql.Internal {
 | 
			
		||||
			_common = common;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		internal bool ReadAnonymousField(List<SelectTableInfo> _tables, StringBuilder field, ReadAnonymousTypeInfo parent, ref int index, Expression exp) {
 | 
			
		||||
		internal bool ReadAnonymousField(List<SelectTableInfo> _tables, StringBuilder field, ReadAnonymousTypeInfo parent, ref int index, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
 | 
			
		||||
			switch (exp.NodeType) {
 | 
			
		||||
				case ExpressionType.Quote: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand);
 | 
			
		||||
				case ExpressionType.Lambda: return ReadAnonymousField(_tables, field, parent, ref index, (exp as LambdaExpression)?.Body);
 | 
			
		||||
				case ExpressionType.Quote: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, getSelectGroupingMapString);
 | 
			
		||||
				case ExpressionType.Lambda: return ReadAnonymousField(_tables, field, parent, ref index, (exp as LambdaExpression)?.Body, getSelectGroupingMapString);
 | 
			
		||||
				case ExpressionType.Negate:
 | 
			
		||||
				case ExpressionType.NegateChecked:
 | 
			
		||||
					parent.DbField = $"-{ExpressionLambdaToSql(exp, _tables, null, SelectTableInfoType.From, true)}";
 | 
			
		||||
					field.Append(", ").Append(parent.DbField).Append(" as").Append(++index);
 | 
			
		||||
					parent.DbField = $"-({ExpressionLambdaToSql(exp, _tables, null, getSelectGroupingMapString, SelectTableInfoType.From, true)})";
 | 
			
		||||
					field.Append(", ").Append(parent.DbField);
 | 
			
		||||
					if (index >= 0) field.Append(" as").Append(++index);
 | 
			
		||||
					return false;
 | 
			
		||||
				case ExpressionType.Convert: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand);
 | 
			
		||||
				case ExpressionType.Convert: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, getSelectGroupingMapString);
 | 
			
		||||
				case ExpressionType.Constant:
 | 
			
		||||
					var constExp = exp as ConstantExpression;
 | 
			
		||||
					parent.DbField = _common.FormatSql("{0}", constExp?.Value);
 | 
			
		||||
					field.Append(", ").Append(parent.DbField).Append(" as").Append(++index);
 | 
			
		||||
					field.Append(", ").Append(parent.DbField);
 | 
			
		||||
					if (index >= 0) field.Append(" as").Append(++index);
 | 
			
		||||
					return false;
 | 
			
		||||
				case ExpressionType.Call:
 | 
			
		||||
					parent.DbField = ExpressionLambdaToSql(exp, _tables, null, SelectTableInfoType.From, true);
 | 
			
		||||
					field.Append(", ").Append(parent.DbField).Append(" as").Append(++index);
 | 
			
		||||
					parent.DbField = ExpressionLambdaToSql(exp, _tables, null, getSelectGroupingMapString, SelectTableInfoType.From, true);
 | 
			
		||||
					field.Append(", ").Append(parent.DbField);
 | 
			
		||||
					if (index >= 0) field.Append(" as").Append(++index);
 | 
			
		||||
					return false;
 | 
			
		||||
				case ExpressionType.MemberAccess:
 | 
			
		||||
					if (_common.GetTableByEntity(exp.Type) != null) { //加载表所有字段
 | 
			
		||||
						var map = new List<SelectColumnInfo>();
 | 
			
		||||
						ExpressionSelectColumn_MemberAccess(_tables, map, SelectTableInfoType.From, exp, true);
 | 
			
		||||
						ExpressionSelectColumn_MemberAccess(_tables, map, SelectTableInfoType.From, exp, true, getSelectGroupingMapString);
 | 
			
		||||
						parent.Consturctor = map.First().Table.Table.Type.GetConstructor(new Type[0]);
 | 
			
		||||
						parent.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties;
 | 
			
		||||
						for (var idx = 0; idx < map.Count; idx++) {
 | 
			
		||||
							var child = new ReadAnonymousTypeInfo { CsName = map[idx].Column.CsName, DbField = $"{map[idx].Table.Alias}.{_common.QuoteSqlName(map[idx].Column.Attribute.Name)}" };
 | 
			
		||||
							field.Append(", ").Append(_common.QuoteReadColumn(map[idx].Column.CsType, child.DbField)).Append(" as").Append(++index);
 | 
			
		||||
							field.Append(", ").Append(_common.QuoteReadColumn(map[idx].Column.CsType, child.DbField));
 | 
			
		||||
							if (index >= 0) field.Append(" as").Append(++index);
 | 
			
		||||
							parent.Childs.Add(child);
 | 
			
		||||
						}
 | 
			
		||||
					} else {
 | 
			
		||||
						parent.DbField = ExpressionLambdaToSql(exp, _tables, null, SelectTableInfoType.From, true);
 | 
			
		||||
						field.Append(", ").Append(parent.DbField).Append(" as").Append(++index);
 | 
			
		||||
						parent.DbField = ExpressionLambdaToSql(exp, _tables, null, getSelectGroupingMapString, SelectTableInfoType.From, true);
 | 
			
		||||
						field.Append(", ").Append(parent.DbField);
 | 
			
		||||
						if (index >= 0) field.Append(" as").Append(++index);
 | 
			
		||||
						return false;
 | 
			
		||||
					}
 | 
			
		||||
					return false;
 | 
			
		||||
@@ -56,10 +61,13 @@ namespace FreeSql.Internal {
 | 
			
		||||
					for (var a = 0; a < newExp.Members.Count; a++) {
 | 
			
		||||
						var child = new ReadAnonymousTypeInfo { CsName = newExp.Members[a].Name, CsType = newExp.Arguments[a].Type };
 | 
			
		||||
						parent.Childs.Add(child);
 | 
			
		||||
						ReadAnonymousField(_tables, field, child, ref index, newExp.Arguments[a]);
 | 
			
		||||
						ReadAnonymousField(_tables, field, child, ref index, newExp.Arguments[a], getSelectGroupingMapString);
 | 
			
		||||
					}
 | 
			
		||||
					return true;
 | 
			
		||||
			}
 | 
			
		||||
			parent.DbField = $"({ExpressionLambdaToSql(exp, _tables, null, getSelectGroupingMapString, SelectTableInfoType.From, true)})";
 | 
			
		||||
			field.Append(", ").Append(parent.DbField);
 | 
			
		||||
			if (index >= 0) field.Append(" as").Append(++index);
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		internal object ReadAnonymous(ReadAnonymousTypeInfo parent, object[] dr, ref int index) {
 | 
			
		||||
@@ -83,28 +91,28 @@ namespace FreeSql.Internal {
 | 
			
		||||
 | 
			
		||||
		internal string ExpressionConstant(ConstantExpression exp) => _common.FormatSql("{0}", exp?.Value);
 | 
			
		||||
 | 
			
		||||
		internal string ExpressionSelectColumn_MemberAccess(List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, Expression exp, bool isQuoteName) {
 | 
			
		||||
			return ExpressionLambdaToSql(exp, _tables, _selectColumnMap, tbtype, isQuoteName);
 | 
			
		||||
		internal string ExpressionSelectColumn_MemberAccess(List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, Expression exp, bool isQuoteName, Func<Expression[], string> getSelectGroupingMapString) {
 | 
			
		||||
			return ExpressionLambdaToSql(exp, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		internal string[] ExpressionSelectColumns_MemberAccess_New_NewArrayInit(List<SelectTableInfo> _tables, Expression exp, bool isQuoteName) {
 | 
			
		||||
		internal string[] ExpressionSelectColumns_MemberAccess_New_NewArrayInit(List<SelectTableInfo> _tables, Expression exp, bool isQuoteName, Func<Expression[], string> getSelectGroupingMapString) {
 | 
			
		||||
			switch (exp?.NodeType) {
 | 
			
		||||
				case ExpressionType.Quote: return ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, (exp as UnaryExpression)?.Operand, isQuoteName);
 | 
			
		||||
				case ExpressionType.Lambda: return ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, (exp as LambdaExpression)?.Body, isQuoteName);
 | 
			
		||||
				case ExpressionType.Convert: return ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, (exp as UnaryExpression)?.Operand, isQuoteName);
 | 
			
		||||
				case ExpressionType.Constant: return new[] { ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, isQuoteName) };
 | 
			
		||||
				case ExpressionType.MemberAccess: return new[] { ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, isQuoteName) };
 | 
			
		||||
				case ExpressionType.Quote: return ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, (exp as UnaryExpression)?.Operand, isQuoteName, getSelectGroupingMapString);
 | 
			
		||||
				case ExpressionType.Lambda: return ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, (exp as LambdaExpression)?.Body, isQuoteName, getSelectGroupingMapString);
 | 
			
		||||
				case ExpressionType.Convert: return ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, (exp as UnaryExpression)?.Operand, isQuoteName, getSelectGroupingMapString);
 | 
			
		||||
				case ExpressionType.Constant: return new[] { ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, isQuoteName, getSelectGroupingMapString) };
 | 
			
		||||
				case ExpressionType.MemberAccess: return new[] { ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, isQuoteName, getSelectGroupingMapString) };
 | 
			
		||||
				case ExpressionType.New:
 | 
			
		||||
					var newExp = exp as NewExpression;
 | 
			
		||||
					if (newExp == null) break;
 | 
			
		||||
					var newExpMembers = new string[newExp.Members.Count];
 | 
			
		||||
					for (var a = 0; a < newExpMembers.Length; a++) newExpMembers[a] = ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, newExp.Arguments[a], isQuoteName);
 | 
			
		||||
					for (var a = 0; a < newExpMembers.Length; a++) newExpMembers[a] = ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, newExp.Arguments[a], isQuoteName, getSelectGroupingMapString);
 | 
			
		||||
					return newExpMembers;
 | 
			
		||||
				case ExpressionType.NewArrayInit:
 | 
			
		||||
					var newArr = exp as NewArrayExpression;
 | 
			
		||||
					if (newArr == null) break;
 | 
			
		||||
					var newArrMembers = new List<string>();
 | 
			
		||||
					foreach (var newArrExp in newArr.Expressions) newArrMembers.AddRange(ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, newArrExp, isQuoteName));
 | 
			
		||||
					foreach (var newArrExp in newArr.Expressions) newArrMembers.AddRange(ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, newArrExp, isQuoteName, getSelectGroupingMapString));
 | 
			
		||||
					return newArrMembers.ToArray();
 | 
			
		||||
			}
 | 
			
		||||
			return new string[0];
 | 
			
		||||
@@ -127,8 +135,8 @@ namespace FreeSql.Internal {
 | 
			
		||||
			{ ExpressionType.Modulo, "%" },
 | 
			
		||||
			{ ExpressionType.Equal, "=" },
 | 
			
		||||
		};
 | 
			
		||||
		internal string ExpressionWhereLambdaNoneForeignObject(List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Expression exp) {
 | 
			
		||||
			var sql = ExpressionLambdaToSql(exp, _tables, _selectColumnMap, SelectTableInfoType.From, true);
 | 
			
		||||
		internal string ExpressionWhereLambdaNoneForeignObject(List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
 | 
			
		||||
			var sql = ExpressionLambdaToSql(exp, _tables, _selectColumnMap, getSelectGroupingMapString, SelectTableInfoType.From, true);
 | 
			
		||||
			switch(sql) {
 | 
			
		||||
				case "1":
 | 
			
		||||
				case "'t'": return "1=1";
 | 
			
		||||
@@ -138,8 +146,8 @@ namespace FreeSql.Internal {
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		internal string ExpressionWhereLambda(List<SelectTableInfo> _tables, Expression exp) {
 | 
			
		||||
			var sql = ExpressionLambdaToSql(exp, _tables, null, SelectTableInfoType.From, true);
 | 
			
		||||
		internal string ExpressionWhereLambda(List<SelectTableInfo> _tables, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
 | 
			
		||||
			var sql = ExpressionLambdaToSql(exp, _tables, null, getSelectGroupingMapString, SelectTableInfoType.From, true);
 | 
			
		||||
			switch (sql) {
 | 
			
		||||
				case "1":
 | 
			
		||||
				case "'t'": return "1=1";
 | 
			
		||||
@@ -148,9 +156,9 @@ namespace FreeSql.Internal {
 | 
			
		||||
				default: return sql;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		internal void ExpressionJoinLambda(List<SelectTableInfo> _tables, SelectTableInfoType tbtype, Expression exp) {
 | 
			
		||||
		internal void ExpressionJoinLambda(List<SelectTableInfo> _tables, SelectTableInfoType tbtype, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
 | 
			
		||||
			var tbidx = _tables.Count;
 | 
			
		||||
			var filter = ExpressionLambdaToSql(exp, _tables, null, tbtype, true);
 | 
			
		||||
			var filter = ExpressionLambdaToSql(exp, _tables, null, getSelectGroupingMapString, tbtype, true);
 | 
			
		||||
			switch (filter) {
 | 
			
		||||
				case "1":
 | 
			
		||||
				case "'t'": filter = "1=1"; break;
 | 
			
		||||
@@ -169,35 +177,46 @@ namespace FreeSql.Internal {
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		internal string ExpressionLambdaToSql(Expression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
 | 
			
		||||
		internal string ExpressionLambdaToSql(Expression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) {
 | 
			
		||||
			switch (exp.NodeType) {
 | 
			
		||||
				case ExpressionType.Quote: return ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, _tables, _selectColumnMap, tbtype, isQuoteName);
 | 
			
		||||
				case ExpressionType.Lambda: return ExpressionLambdaToSql((exp as LambdaExpression)?.Body, _tables, _selectColumnMap, tbtype, isQuoteName);
 | 
			
		||||
				case ExpressionType.Convert: return ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, _tables, _selectColumnMap, tbtype, isQuoteName);
 | 
			
		||||
				case ExpressionType.Quote: return ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
 | 
			
		||||
				case ExpressionType.Lambda: return ExpressionLambdaToSql((exp as LambdaExpression)?.Body, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
 | 
			
		||||
				case ExpressionType.Convert: return ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
 | 
			
		||||
				case ExpressionType.Negate:
 | 
			
		||||
				case ExpressionType.NegateChecked: return "-" + ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, _tables, _selectColumnMap, tbtype, isQuoteName);
 | 
			
		||||
				case ExpressionType.NegateChecked: return "-" + ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
 | 
			
		||||
				case ExpressionType.Constant: return _common.FormatSql("{0}", (exp as ConstantExpression)?.Value);
 | 
			
		||||
				case ExpressionType.Conditional:
 | 
			
		||||
					var condExp = exp as ConditionalExpression;
 | 
			
		||||
					return $"case when {ExpressionLambdaToSql(condExp.Test, _tables, _selectColumnMap, tbtype, isQuoteName)} then {ExpressionLambdaToSql(condExp.IfTrue, _tables, _selectColumnMap, tbtype, isQuoteName)} else {ExpressionLambdaToSql(condExp.IfFalse, _tables, _selectColumnMap, tbtype, isQuoteName)} end";
 | 
			
		||||
					return $"case when {ExpressionLambdaToSql(condExp.Test, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName)} then {ExpressionLambdaToSql(condExp.IfTrue, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName)} else {ExpressionLambdaToSql(condExp.IfFalse, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName)} end";
 | 
			
		||||
				case ExpressionType.Call:
 | 
			
		||||
					var exp3 = exp as MethodCallExpression;
 | 
			
		||||
					switch (exp3.Object?.Type.FullName ?? exp3.Method.DeclaringType.FullName) {
 | 
			
		||||
						case "System.String": return ExpressionLambdaToSqlCallString(exp3, _tables, _selectColumnMap, tbtype, isQuoteName);
 | 
			
		||||
						case "System.Math": return ExpressionLambdaToSqlCallMath(exp3, _tables, _selectColumnMap, tbtype, isQuoteName);
 | 
			
		||||
						case "System.DateTime": return ExpressionLambdaToSqlCallDateTime(exp3, _tables, _selectColumnMap, tbtype, isQuoteName);
 | 
			
		||||
						case "System.TimeSpan": return ExpressionLambdaToSqlCallTimeSpan(exp3, _tables, _selectColumnMap, tbtype, isQuoteName);
 | 
			
		||||
						case "System.Convert": return ExpressionLambdaToSqlCallConvert(exp3, _tables, _selectColumnMap, tbtype, isQuoteName);
 | 
			
		||||
					var callType = exp3.Object?.Type ?? exp3.Method.DeclaringType;
 | 
			
		||||
					switch (callType.FullName) {
 | 
			
		||||
						case "System.String": return ExpressionLambdaToSqlCallString(exp3, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
 | 
			
		||||
						case "System.Math": return ExpressionLambdaToSqlCallMath(exp3, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
 | 
			
		||||
						case "System.DateTime": return ExpressionLambdaToSqlCallDateTime(exp3, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
 | 
			
		||||
						case "System.TimeSpan": return ExpressionLambdaToSqlCallTimeSpan(exp3, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
 | 
			
		||||
						case "System.Convert": return ExpressionLambdaToSqlCallConvert(exp3, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
 | 
			
		||||
					}
 | 
			
		||||
					throw new Exception($"MySqlExpression 未现实函数表达式 {exp3} 解析");
 | 
			
		||||
					if (callType.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`")) {
 | 
			
		||||
						switch (exp3.Method.Name) {
 | 
			
		||||
							case "Count": return "count(1)";
 | 
			
		||||
							case "Sum": return $"sum({ExpressionLambdaToSql(exp3.Arguments[0], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName)})";
 | 
			
		||||
							case "Avg": return $"avg({ExpressionLambdaToSql(exp3.Arguments[0], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName)})";
 | 
			
		||||
							case "Max": return $"max({ExpressionLambdaToSql(exp3.Arguments[0], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName)})";
 | 
			
		||||
							case "Min": return $"min({ExpressionLambdaToSql(exp3.Arguments[0], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName)})";
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					throw new Exception($"未现实函数表达式 {exp3} 解析");
 | 
			
		||||
				case ExpressionType.MemberAccess:
 | 
			
		||||
					var exp4 = exp as MemberExpression;
 | 
			
		||||
					if (exp4.Expression != null && exp4.Expression.Type.IsArray == false && exp4.Expression.Type.FullName.StartsWith("System.Nullable`1[")) return ExpressionLambdaToSql(exp4.Expression, _tables, _selectColumnMap, tbtype, isQuoteName);
 | 
			
		||||
					if (exp4.Expression != null && exp4.Expression.Type.IsArray == false && exp4.Expression.Type.FullName.StartsWith("System.Nullable`1[")) return ExpressionLambdaToSql(exp4.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
 | 
			
		||||
					var extRet = "";
 | 
			
		||||
					switch (exp4.Expression?.Type.FullName ?? exp4.Type.FullName) {
 | 
			
		||||
						case "System.String": extRet = ExpressionLambdaToSqlMemberAccessString(exp4, _tables, _selectColumnMap, tbtype, isQuoteName); break;
 | 
			
		||||
						case "System.DateTime": extRet = ExpressionLambdaToSqlMemberAccessDateTime(exp4, _tables, _selectColumnMap, tbtype, isQuoteName); break;
 | 
			
		||||
						case "System.TimeSpan": extRet = ExpressionLambdaToSqlMemberAccessTimeSpan(exp4, _tables, _selectColumnMap, tbtype, isQuoteName); break;
 | 
			
		||||
					var memberType = exp4.Expression?.Type ?? exp4.Type;
 | 
			
		||||
					switch (memberType.FullName) {
 | 
			
		||||
						case "System.String": extRet = ExpressionLambdaToSqlMemberAccessString(exp4, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); break;
 | 
			
		||||
						case "System.DateTime": extRet = ExpressionLambdaToSqlMemberAccessDateTime(exp4, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); break;
 | 
			
		||||
						case "System.TimeSpan": extRet = ExpressionLambdaToSqlMemberAccessTimeSpan(exp4, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); break;
 | 
			
		||||
					}
 | 
			
		||||
					if (string.IsNullOrEmpty(extRet) == false) return extRet;
 | 
			
		||||
 | 
			
		||||
@@ -228,7 +247,18 @@ namespace FreeSql.Internal {
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
					if (expStack.First().NodeType != ExpressionType.Parameter) return _common.FormatSql("{0}", Expression.Lambda(exp).Compile().DynamicInvoke());
 | 
			
		||||
					if (callExp != null) return ExpressionLambdaToSql(callExp, _tables, _selectColumnMap, tbtype, isQuoteName);
 | 
			
		||||
					if (callExp != null) return ExpressionLambdaToSql(callExp, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
 | 
			
		||||
					if (getSelectGroupingMapString != null && expStack.First().Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`")) {
 | 
			
		||||
						var expText = getSelectGroupingMapString(expStack.Where((a, b) => b >= 2).ToArray());
 | 
			
		||||
						if (string.IsNullOrEmpty(expText) == false) return expText;
 | 
			
		||||
					}
 | 
			
		||||
					//if (exp4.Expression != null && exp4.Expression.NodeType == ExpressionType.MemberAccess) {
 | 
			
		||||
					//	var keyExp = exp4.Expression as MemberExpression;
 | 
			
		||||
					//	if (keyExp.Member.Name == "Key" && keyExp.Expression.Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`")) {
 | 
			
		||||
					//		var expText = getSelectGroupingMapString(exp4)
 | 
			
		||||
					//	}
 | 
			
		||||
					//}
 | 
			
		||||
 | 
			
		||||
					if (_tables == null) {
 | 
			
		||||
						var pp = expStack.Pop() as ParameterExpression;
 | 
			
		||||
						var memberExp = expStack.Pop() as MemberExpression;
 | 
			
		||||
@@ -300,12 +330,12 @@ namespace FreeSql.Internal {
 | 
			
		||||
			if (expBinary == null) return "";
 | 
			
		||||
			if (expBinary.NodeType == ExpressionType.Coalesce) {
 | 
			
		||||
				return _common.IsNull(
 | 
			
		||||
					ExpressionLambdaToSql(expBinary.Left, _tables, _selectColumnMap, tbtype, isQuoteName),
 | 
			
		||||
					ExpressionLambdaToSql(expBinary.Right, _tables, _selectColumnMap, tbtype, isQuoteName));
 | 
			
		||||
					ExpressionLambdaToSql(expBinary.Left, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName),
 | 
			
		||||
					ExpressionLambdaToSql(expBinary.Right, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName));
 | 
			
		||||
			}
 | 
			
		||||
			if (dicExpressionOperator.TryGetValue(expBinary.NodeType, out var tryoper) == false) return "";
 | 
			
		||||
			var left = ExpressionLambdaToSql(expBinary.Left, _tables, _selectColumnMap, tbtype, isQuoteName);
 | 
			
		||||
			var right = ExpressionLambdaToSql(expBinary.Right, _tables, _selectColumnMap, tbtype, isQuoteName);
 | 
			
		||||
			var left = ExpressionLambdaToSql(expBinary.Left, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
 | 
			
		||||
			var right = ExpressionLambdaToSql(expBinary.Right, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
 | 
			
		||||
			if (left == "NULL") {
 | 
			
		||||
				var tmp = right;
 | 
			
		||||
				right = left;
 | 
			
		||||
@@ -316,13 +346,13 @@ namespace FreeSql.Internal {
 | 
			
		||||
			return $"{left} {tryoper} {right}";
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		internal abstract string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
 | 
			
		||||
		internal abstract string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
 | 
			
		||||
		internal abstract string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
 | 
			
		||||
		internal abstract string ExpressionLambdaToSqlCallString(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
 | 
			
		||||
		internal abstract string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
 | 
			
		||||
		internal abstract string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
 | 
			
		||||
		internal abstract string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
 | 
			
		||||
		internal abstract string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
 | 
			
		||||
		internal abstract string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName);
 | 
			
		||||
		internal abstract string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName);
 | 
			
		||||
		internal abstract string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName);
 | 
			
		||||
		internal abstract string ExpressionLambdaToSqlCallString(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName);
 | 
			
		||||
		internal abstract string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName);
 | 
			
		||||
		internal abstract string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName);
 | 
			
		||||
		internal abstract string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName);
 | 
			
		||||
		internal abstract string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
		}
 | 
			
		||||
		public abstract List<T1> ExecuteDeleted();
 | 
			
		||||
 | 
			
		||||
		public IDelete<T1> Where(Expression<Func<T1, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambdaNoneForeignObject(null, null, exp?.Body));
 | 
			
		||||
		public IDelete<T1> Where(Expression<Func<T1, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambdaNoneForeignObject(null, null, exp?.Body, null));
 | 
			
		||||
		public IDelete<T1> Where(string sql, object parms = null) {
 | 
			
		||||
			if (string.IsNullOrEmpty(sql)) return this;
 | 
			
		||||
			if (++_whereTimes > 1) _where.Append(" AND ");
 | 
			
		||||
 
 | 
			
		||||
@@ -40,13 +40,13 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
		public abstract List<T1> ExecuteInserted();
 | 
			
		||||
 | 
			
		||||
		public IInsert<T1> IgnoreColumns(Expression<Func<T1, object>> columns) {
 | 
			
		||||
			var cols = _commonExpression.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(null, columns?.Body, false).Distinct();
 | 
			
		||||
			var cols = _commonExpression.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(null, columns?.Body, false, null).Distinct();
 | 
			
		||||
			_ignore.Clear();
 | 
			
		||||
			foreach (var col in cols) _ignore.Add(col, true);
 | 
			
		||||
			return this;
 | 
			
		||||
		}
 | 
			
		||||
		public IInsert<T1> InsertColumns(Expression<Func<T1, object>> columns) {
 | 
			
		||||
			var cols = _commonExpression.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(null, columns?.Body, false).ToDictionary(a => a, a => true);
 | 
			
		||||
			var cols = _commonExpression.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(null, columns?.Body, false, null).ToDictionary(a => a, a => true);
 | 
			
		||||
			_ignore.Clear();
 | 
			
		||||
			foreach (var col in _table.Columns.Values)
 | 
			
		||||
				if (cols.ContainsKey(col.Attribute.Name) == false)
 | 
			
		||||
 
 | 
			
		||||
@@ -108,7 +108,8 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		public TSelect OrderBy(string sql, object parms = null) {
 | 
			
		||||
			if (string.IsNullOrEmpty(sql)) _orderby = null;
 | 
			
		||||
			_orderby = string.Concat(string.IsNullOrEmpty(_orderby) ? " \r\nORDER BY " : "", _orderby, sql);
 | 
			
		||||
			var isnull = string.IsNullOrEmpty(_orderby);
 | 
			
		||||
			_orderby = string.Concat(isnull ? " \r\nORDER BY " : "", _orderby, isnull ? "" : ", ", sql);
 | 
			
		||||
			if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(sql, parms));
 | 
			
		||||
			return this as TSelect;
 | 
			
		||||
		}
 | 
			
		||||
@@ -146,14 +147,14 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
		public List<T1> ToList() {
 | 
			
		||||
			return this.ToList<T1>(this.GetAllField());
 | 
			
		||||
			return this.ToListMapReader<T1>(this.GetAllField());
 | 
			
		||||
		}
 | 
			
		||||
		public T1 ToOne() {
 | 
			
		||||
			this.Limit(1);
 | 
			
		||||
			return ToList().FirstOrDefault();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		protected List<TReturn> ToList<TReturn>((ReadAnonymousTypeInfo map, string field) af) {
 | 
			
		||||
		protected List<TReturn> ToListMapReader<TReturn>((ReadAnonymousTypeInfo map, string field) af) {
 | 
			
		||||
			var sql = this.ToSql(af.field);
 | 
			
		||||
			if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = $"{sql}{string.Join("|", _params.Select(a => a.Value))}";
 | 
			
		||||
 | 
			
		||||
@@ -171,7 +172,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
			var field = new StringBuilder();
 | 
			
		||||
			var index = 0;
 | 
			
		||||
 | 
			
		||||
			_commonExpression.ReadAnonymousField(_tables, field, map, ref index, newexp);
 | 
			
		||||
			_commonExpression.ReadAnonymousField(_tables, field, map, ref index, newexp, null);
 | 
			
		||||
			return (map, map.Childs.Count > 0 ? field.Remove(0, 2).ToString() : null);
 | 
			
		||||
		}
 | 
			
		||||
		protected (ReadAnonymousTypeInfo map, string field) GetAllField() {
 | 
			
		||||
@@ -222,31 +223,38 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
		}
 | 
			
		||||
		#region common
 | 
			
		||||
 | 
			
		||||
		protected TMember InternalAvg<TMember>(Expression exp) => this.ToList<TMember>($"avg({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true)})").FirstOrDefault();
 | 
			
		||||
		protected TMember InternalMax<TMember>(Expression exp) => this.ToList<TMember>($"max({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true)})").FirstOrDefault();
 | 
			
		||||
		protected TMember InternalMin<TMember>(Expression exp) => this.ToList<TMember>($"min({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true)})").FirstOrDefault();
 | 
			
		||||
		protected TMember InternalSum<TMember>(Expression exp) => this.ToList<TMember>($"sum({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true)})").FirstOrDefault();
 | 
			
		||||
		protected TMember InternalAvg<TMember>(Expression exp) => this.ToList<TMember>($"avg({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)})").FirstOrDefault();
 | 
			
		||||
		protected TMember InternalMax<TMember>(Expression exp) => this.ToList<TMember>($"max({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)})").FirstOrDefault();
 | 
			
		||||
		protected TMember InternalMin<TMember>(Expression exp) => this.ToList<TMember>($"min({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)})").FirstOrDefault();
 | 
			
		||||
		protected TMember InternalSum<TMember>(Expression exp) => this.ToList<TMember>($"sum({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)})").FirstOrDefault();
 | 
			
		||||
 | 
			
		||||
		protected TSelect InternalGroupBy(Expression columns) {
 | 
			
		||||
			return this.GroupBy(string.Join(", ", _commonExpression.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, columns, true)));
 | 
			
		||||
		protected ISelectGrouping<TKey> InternalGroupBy<TKey>(Expression columns) {
 | 
			
		||||
			var map = new ReadAnonymousTypeInfo();
 | 
			
		||||
			var field = new StringBuilder();
 | 
			
		||||
			var index = -10000; //临时规则,不返回 as1
 | 
			
		||||
 | 
			
		||||
			_commonExpression.ReadAnonymousField(_tables, field, map, ref index, columns, null);
 | 
			
		||||
			this.GroupBy(map.Childs.Count > 0 ? field.Remove(0, 2).ToString() : null);
 | 
			
		||||
			return new SelectGroupingProvider<TKey>(this, map, _commonExpression);
 | 
			
		||||
		}
 | 
			
		||||
		protected TSelect InternalJoin(Expression exp, SelectTableInfoType joinType) {
 | 
			
		||||
			_commonExpression.ExpressionJoinLambda(_tables, joinType, exp);
 | 
			
		||||
			_commonExpression.ExpressionJoinLambda(_tables, joinType, exp, null);
 | 
			
		||||
			return this as TSelect;
 | 
			
		||||
		}
 | 
			
		||||
		protected TSelect InternalJoin<T2>(Expression exp, SelectTableInfoType joinType) {
 | 
			
		||||
			var tb = _commonUtils.GetTableByEntity(typeof(T2));
 | 
			
		||||
			if (tb == null) throw new ArgumentException("T2 类型错误");
 | 
			
		||||
			_tables.Add(new SelectTableInfo { Table = tb, Alias = $"IJ{_tables.Count}", On = null, Type = joinType });
 | 
			
		||||
			_commonExpression.ExpressionJoinLambda(_tables, joinType, exp);
 | 
			
		||||
			_commonExpression.ExpressionJoinLambda(_tables, joinType, exp, null);
 | 
			
		||||
			return this as TSelect;
 | 
			
		||||
		}
 | 
			
		||||
		protected TSelect InternalOrderBy(Expression column) => this.OrderBy(_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true));
 | 
			
		||||
		protected TSelect InternalOrderByDescending(Expression column) => this.OrderBy($"{_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true)} DESC");
 | 
			
		||||
		protected TSelect InternalOrderBy(Expression column) => this.OrderBy(_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true, null));
 | 
			
		||||
		protected TSelect InternalOrderByDescending(Expression column) => this.OrderBy($"{_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true, null)} DESC");
 | 
			
		||||
 | 
			
		||||
		protected List<TReturn> InternalToList<TReturn>(Expression select) => this.ToList<TReturn>(this.GetNewExpressionField(select as NewExpression));
 | 
			
		||||
		protected List<TReturn> InternalToList<TReturn>(Expression select) => this.ToListMapReader<TReturn>(this.GetNewExpressionField(select as NewExpression));
 | 
			
		||||
		protected string InternalToSql<TReturn>(Expression select) => this.ToSql(this.GetNewExpressionField(select as NewExpression).field);
 | 
			
		||||
 | 
			
		||||
		protected TSelect InternalWhere(Expression exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp));
 | 
			
		||||
		protected TSelect InternalWhere(Expression exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp, null));
 | 
			
		||||
 | 
			
		||||
		protected TSelect InternalJoin(Expression exp) {
 | 
			
		||||
			return this as TSelect;
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.Avg<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.GroupBy(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, object>> columns) => this.InternalGroupBy(columns?.Body);
 | 
			
		||||
		ISelectGrouping<TKey> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TKey>> exp) => this.InternalGroupBy<TKey>(exp?.Body);
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.Max<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TMember>> column) => this.InternalMax<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
@@ -36,8 +36,8 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		List<TReturn> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.ToList<TReturn>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body, null));
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body, null)) : this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -3,6 +3,7 @@ using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Linq.Expressions;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
@@ -26,11 +27,10 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
					switch (expCall.Method.Name) {
 | 
			
		||||
						case "Where": this.InternalWhere(expCall.Arguments[0]); break;
 | 
			
		||||
						case "WhereIf":
 | 
			
		||||
							var whereIfCond = _commonExpression.ExpressionSelectColumn_MemberAccess(null, null, SelectTableInfoType.From, expCall.Arguments[0], false);
 | 
			
		||||
							var whereIfCond = _commonExpression.ExpressionSelectColumn_MemberAccess(null, null, SelectTableInfoType.From, expCall.Arguments[0], false, null);
 | 
			
		||||
							if (whereIfCond == "1" || whereIfCond == "'t'")
 | 
			
		||||
								this.InternalWhere(expCall.Arguments[1]);
 | 
			
		||||
							break;
 | 
			
		||||
						case "GroupBy": this.InternalGroupBy(expCall.Arguments[0]); break;
 | 
			
		||||
						case "OrderBy": this.InternalOrderBy(expCall.Arguments[0]); break;
 | 
			
		||||
						case "OrderByDescending": this.InternalOrderByDescending(expCall.Arguments[0]); break;
 | 
			
		||||
 | 
			
		||||
@@ -74,7 +74,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		public abstract ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> From<T2, T3, T4, T5, T6, T7, T8, T9, T10>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class;// { this.InternalFrom(exp?.Body); var ret = new Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret); return ret; }
 | 
			
		||||
 | 
			
		||||
		public ISelect<T1> GroupBy<TReturn>(Expression<Func<T1, TReturn>> columns) => this.InternalGroupBy(columns?.Body);
 | 
			
		||||
		public ISelectGrouping<TKey> GroupBy<TKey>(Expression<Func<T1, TKey>> columns) => this.InternalGroupBy<TKey>(columns);
 | 
			
		||||
 | 
			
		||||
		public TMember Max<TMember>(Expression<Func<T1, TMember>> column) => this.InternalMax<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
@@ -87,6 +87,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
		public TMember Sum<TMember>(Expression<Func<T1, TMember>> column) => this.InternalSum<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
		public List<TReturn> ToList<TReturn>(Expression<Func<T1, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
 | 
			
		||||
		public string ToSql<TReturn>(Expression<Func<T1, TReturn>> select) => this.InternalToSql<TReturn>(select?.Body);
 | 
			
		||||
 | 
			
		||||
		public ISelect<T1> Where(Expression<Func<T1, bool>> exp) => this.InternalWhere(exp?.Body);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,35 +0,0 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq.Expressions;
 | 
			
		||||
 | 
			
		||||
namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
	abstract class Select2Provider<T1, T2> : Select0Provider<ISelect<T1, T2>, T1>, ISelect<T1, T2>
 | 
			
		||||
			where T1 : class
 | 
			
		||||
			where T2 : class {
 | 
			
		||||
 | 
			
		||||
		public Select2Provider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) {
 | 
			
		||||
			if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure<T2>();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2>.Avg<TMember>(Expression<Func<T1, T2, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2> ISelect<T1, T2>.GroupBy(Expression<Func<T1, T2, object>> columns) => this.InternalGroupBy(columns?.Body);
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2>.Max<TMember>(Expression<Func<T1, T2, TMember>> column) => this.InternalMax<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2>.Min<TMember>(Expression<Func<T1, T2, TMember>> column) => this.InternalMin<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2> ISelect<T1, T2>.OrderBy<TMember>(Expression<Func<T1, T2, TMember>> column) => this.InternalOrderBy(column?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2> ISelect<T1, T2>.OrderByDescending<TMember>(Expression<Func<T1, T2, TMember>> column) => this.InternalOrderByDescending(column?.Body);
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2>.Sum<TMember>(Expression<Func<T1, T2, TMember>> column) => this.InternalSum<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
		List<TReturn> ISelect<T1, T2>.ToList<TReturn>(Expression<Func<T1, T2, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2> ISelect<T1, T2>.Where(Expression<Func<T1, T2, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2> ISelect<T1, T2>.WhereIf(bool condition, Expression<Func<T1, T2, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -15,7 +15,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2, T3>.Avg<TMember>(Expression<Func<T1, T2, T3, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3> ISelect<T1, T2, T3>.GroupBy(Expression<Func<T1, T2, T3, object>> columns) => this.InternalGroupBy(columns?.Body);
 | 
			
		||||
		ISelectGrouping<TKey> ISelect<T1, T2, T3>.GroupBy<TKey>(Expression<Func<T1, T2, T3, TKey>> exp) => this.InternalGroupBy<TKey>(exp?.Body);
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2, T3>.Max<TMember>(Expression<Func<T1, T2, T3, TMember>> column) => this.InternalMax<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
@@ -29,8 +29,8 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		List<TReturn> ISelect<T1, T2, T3>.ToList<TReturn>(Expression<Func<T1, T2, T3, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3> ISelect<T1, T2, T3>.Where(Expression<Func<T1, T2, T3, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
 | 
			
		||||
		ISelect<T1, T2, T3> ISelect<T1, T2, T3>.Where(Expression<Func<T1, T2, T3, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body, null));
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3> ISelect<T1, T2, T3>.WhereIf(bool condition, Expression<Func<T1, T2, T3, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
 | 
			
		||||
		ISelect<T1, T2, T3> ISelect<T1, T2, T3>.WhereIf(bool condition, Expression<Func<T1, T2, T3, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body, null)) : this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -16,7 +16,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2, T3, T4>.Avg<TMember>(Expression<Func<T1, T2, T3, T4, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4> ISelect<T1, T2, T3, T4>.GroupBy(Expression<Func<T1, T2, T3, T4, object>> columns) => this.InternalGroupBy(columns?.Body);
 | 
			
		||||
		ISelectGrouping<TKey> ISelect<T1, T2, T3, T4>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, TKey>> exp) => this.InternalGroupBy<TKey>(exp?.Body);
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2, T3, T4>.Max<TMember>(Expression<Func<T1, T2, T3, T4, TMember>> column) => this.InternalMax<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
@@ -30,8 +30,8 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		List<TReturn> ISelect<T1, T2, T3, T4>.ToList<TReturn>(Expression<Func<T1, T2, T3, T4, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4> ISelect<T1, T2, T3, T4>.Where(Expression<Func<T1, T2, T3, T4, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
 | 
			
		||||
		ISelect<T1, T2, T3, T4> ISelect<T1, T2, T3, T4>.Where(Expression<Func<T1, T2, T3, T4, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body, null));
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4> ISelect<T1, T2, T3, T4>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
 | 
			
		||||
		ISelect<T1, T2, T3, T4> ISelect<T1, T2, T3, T4>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body, null)) : this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2, T3, T4, T5>.Avg<TMember>(Expression<Func<T1, T2, T3, T4, T5, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5> ISelect<T1, T2, T3, T4, T5>.GroupBy(Expression<Func<T1, T2, T3, T4, T5, object>> columns) => this.InternalGroupBy(columns?.Body);
 | 
			
		||||
		ISelectGrouping<TKey> ISelect<T1, T2, T3, T4, T5>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, T5, TKey>> exp) => this.InternalGroupBy<TKey>(exp?.Body);
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2, T3, T4, T5>.Max<TMember>(Expression<Func<T1, T2, T3, T4, T5, TMember>> column) => this.InternalMax<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
@@ -31,8 +31,8 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		List<TReturn> ISelect<T1, T2, T3, T4, T5>.ToList<TReturn>(Expression<Func<T1, T2, T3, T4, T5, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5> ISelect<T1, T2, T3, T4, T5>.Where(Expression<Func<T1, T2, T3, T4, T5, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5> ISelect<T1, T2, T3, T4, T5>.Where(Expression<Func<T1, T2, T3, T4, T5, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body, null));
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5> ISelect<T1, T2, T3, T4, T5>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5> ISelect<T1, T2, T3, T4, T5>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body, null)) : this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2, T3, T4, T5, T6>.Avg<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6> ISelect<T1, T2, T3, T4, T5, T6>.GroupBy(Expression<Func<T1, T2, T3, T4, T5, T6, object>> columns) => this.InternalGroupBy(columns?.Body);
 | 
			
		||||
		ISelectGrouping<TKey> ISelect<T1, T2, T3, T4, T5, T6>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, T5, T6, TKey>> exp) => this.InternalGroupBy<TKey>(exp?.Body);
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2, T3, T4, T5, T6>.Max<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, TMember>> column) => this.InternalMax<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
@@ -32,8 +32,8 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		List<TReturn> ISelect<T1, T2, T3, T4, T5, T6>.ToList<TReturn>(Expression<Func<T1, T2, T3, T4, T5, T6, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6> ISelect<T1, T2, T3, T4, T5, T6>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6> ISelect<T1, T2, T3, T4, T5, T6>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body, null));
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6> ISelect<T1, T2, T3, T4, T5, T6>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6> ISelect<T1, T2, T3, T4, T5, T6>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body, null)) : this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -19,7 +19,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2, T3, T4, T5, T6, T7>.Avg<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7> ISelect<T1, T2, T3, T4, T5, T6, T7>.GroupBy(Expression<Func<T1, T2, T3, T4, T5, T6, T7, object>> columns) => this.InternalGroupBy(columns?.Body);
 | 
			
		||||
		ISelectGrouping<TKey> ISelect<T1, T2, T3, T4, T5, T6, T7>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, TKey>> exp) => this.InternalGroupBy<TKey>(exp?.Body);
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2, T3, T4, T5, T6, T7>.Max<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, TMember>> column) => this.InternalMax<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
@@ -33,8 +33,8 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		List<TReturn> ISelect<T1, T2, T3, T4, T5, T6, T7>.ToList<TReturn>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7> ISelect<T1, T2, T3, T4, T5, T6, T7>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7> ISelect<T1, T2, T3, T4, T5, T6, T7>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body, null));
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7> ISelect<T1, T2, T3, T4, T5, T6, T7>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7> ISelect<T1, T2, T3, T4, T5, T6, T7>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body, null)) : this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -20,7 +20,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.Avg<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7, T8> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.GroupBy(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, object>> columns) => this.InternalGroupBy(columns?.Body);
 | 
			
		||||
		ISelectGrouping<TKey> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, TKey>> exp) => this.InternalGroupBy<TKey>(exp?.Body);
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.Max<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, TMember>> column) => this.InternalMax<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
@@ -34,8 +34,8 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		List<TReturn> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.ToList<TReturn>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7, T8> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7, T8> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body, null));
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7, T8> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7, T8> ISelect<T1, T2, T3, T4, T5, T6, T7, T8>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body, null)) : this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -21,7 +21,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.Avg<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TMember>> column) => this.InternalAvg<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.GroupBy(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, object>> columns) => this.InternalGroupBy(columns?.Body);
 | 
			
		||||
		ISelectGrouping<TKey> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.GroupBy<TKey>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TKey>> exp) => this.InternalGroupBy<TKey>(exp?.Body);
 | 
			
		||||
 | 
			
		||||
		TMember ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.Max<TMember>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TMember>> column) => this.InternalMax<TMember>(column?.Body);
 | 
			
		||||
 | 
			
		||||
@@ -35,8 +35,8 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		List<TReturn> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.ToList<TReturn>(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TReturn>> select) => this.InternalToList<TReturn>(select?.Body);
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body));
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.Where(Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body, null));
 | 
			
		||||
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body)) : this;
 | 
			
		||||
		ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>.WhereIf(bool condition, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, bool>> exp) => condition ? this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp?.Body, null)) : this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,42 +1,72 @@
 | 
			
		||||
//using FreeSql.Internal.Model;
 | 
			
		||||
//using System;
 | 
			
		||||
//using System.Collections.Generic;
 | 
			
		||||
//using System.Linq.Expressions;
 | 
			
		||||
//using System.Text;
 | 
			
		||||
using FreeSql.Internal.Model;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Linq.Expressions;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
//namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
//	public class SelectGroupingProvider<T1, T2> : ISelectGrouping<T1> where T2 : class {
 | 
			
		||||
namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
	class SelectGroupingProvider<T1> : ISelectGrouping<T1> {
 | 
			
		||||
 | 
			
		||||
//		internal Select1Provider<T2> _select;
 | 
			
		||||
//		internal ReadAnonymousTypeInfo _map;
 | 
			
		||||
//		internal CommonExpression _comonExp;
 | 
			
		||||
//		internal SelectTableInfo _table;
 | 
			
		||||
//		SelectGroupingProvider(CommonExpression comonExp, Expression exp) {
 | 
			
		||||
//			_comonExp = comonExp;
 | 
			
		||||
//			//var columns = _comonExp.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_select._tables, columns, true);
 | 
			
		||||
//			_table = new SelectTableInfo { Alias = "", On = "", Table = _comonExp._common.GetTableByEntity(typeof(T1)), Type = SelectTableInfoType.From };
 | 
			
		||||
//		}
 | 
			
		||||
		internal object _select;
 | 
			
		||||
		internal ReadAnonymousTypeInfo _map;
 | 
			
		||||
		internal CommonExpression _comonExp;
 | 
			
		||||
		public SelectGroupingProvider(object select, ReadAnonymousTypeInfo map, CommonExpression comonExp) {
 | 
			
		||||
			_select = select;
 | 
			
		||||
			_map = map;
 | 
			
		||||
			_comonExp = comonExp;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
//		public ISelectGrouping<T1> Having(Expression<Func<ISelectGroupingAggregate<T1>, bool>> exp) {
 | 
			
		||||
//			_select.Having(_comonExp.ExpressionWhereLambda(new List<SelectTableInfo>(new[] { _table }), exp));
 | 
			
		||||
//			return this;
 | 
			
		||||
//		}
 | 
			
		||||
		string getSelectGroupingMapString(Expression[] members) {
 | 
			
		||||
			var read = _map;
 | 
			
		||||
			for (var a = 0; a < members.Length; a++) {
 | 
			
		||||
				read = read.Childs.Where(z => z.CsName == (members[a] as MemberExpression)?.Member.Name).FirstOrDefault();
 | 
			
		||||
				if (read == null) return null;
 | 
			
		||||
			}
 | 
			
		||||
			return read.DbField;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
//		public ISelectGrouping<T1> OrderBy<TMember>(Expression<Func<ISelectGroupingAggregate<T1>, TMember>> column) {
 | 
			
		||||
//			var columnMap = new List<SelectColumnInfo>();
 | 
			
		||||
//			_comonExp.ExpressionSelectColumn_MemberAccess(new List<SelectTableInfo>(new[] { _table }), columnMap, SelectTableInfoType.From, column, true);
 | 
			
		||||
		public ISelectGrouping<T1> Having(Expression<Func<ISelectGroupingAggregate<T1>, bool>> exp) {
 | 
			
		||||
			var sql = _comonExp.ExpressionWhereLambda(null, exp, getSelectGroupingMapString);
 | 
			
		||||
			var method = _select.GetType().GetMethod("Having", new[] { typeof(string), typeof(object) });
 | 
			
		||||
			method.Invoke(_select, new object[] { sql, null });
 | 
			
		||||
			return this;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
//			_select.OrderBy();
 | 
			
		||||
//			return this;
 | 
			
		||||
//		}
 | 
			
		||||
		public ISelectGrouping<T1> OrderBy<TMember>(Expression<Func<ISelectGroupingAggregate<T1>, TMember>> column) {
 | 
			
		||||
			var sql = _comonExp.ExpressionWhereLambda(null, column, getSelectGroupingMapString);
 | 
			
		||||
			var method = _select.GetType().GetMethod("OrderBy", new[] { typeof(string), typeof(object) });
 | 
			
		||||
			method.Invoke(_select, new object[] { sql, null });
 | 
			
		||||
			return this;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
//		public ISelectGrouping<T1> OrderByDescending<TMember>(Expression<Func<ISelectGroupingAggregate<T1>, TMember>> column) {
 | 
			
		||||
//			_select.OrderBy(" DESC");
 | 
			
		||||
//			return this;
 | 
			
		||||
//		}
 | 
			
		||||
		public ISelectGrouping<T1> OrderByDescending<TMember>(Expression<Func<ISelectGroupingAggregate<T1>, TMember>> column) {
 | 
			
		||||
			var sql = _comonExp.ExpressionWhereLambda(null, column, getSelectGroupingMapString);
 | 
			
		||||
			var method = _select.GetType().GetMethod("OrderBy", new[] { typeof(string), typeof(object) });
 | 
			
		||||
			method.Invoke(_select, new object[] { $"{sql} DESC", null });
 | 
			
		||||
			return this;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
//		public List<TReturn> ToList<TReturn>(Expression<Func<ISelectGroupingAggregate<T1>, TReturn>> select) {
 | 
			
		||||
//			throw new NotImplementedException();
 | 
			
		||||
//		}
 | 
			
		||||
//	}
 | 
			
		||||
//}
 | 
			
		||||
		public List<TReturn> ToList<TReturn>(Expression<Func<ISelectGroupingAggregate<T1>, TReturn>> select) {
 | 
			
		||||
			var map = new ReadAnonymousTypeInfo();
 | 
			
		||||
			var field = new StringBuilder();
 | 
			
		||||
			var index = 0;
 | 
			
		||||
 | 
			
		||||
			_comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString);
 | 
			
		||||
			var method = _select.GetType().GetMethod("ToListMapReader", BindingFlags.Instance | BindingFlags.NonPublic);
 | 
			
		||||
			method = method.MakeGenericMethod(typeof(TReturn));
 | 
			
		||||
			return method.Invoke(_select, new object[] { (map, map.Childs.Count > 0 ? field.Remove(0, 2).ToString() : null) }) as List<TReturn>;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public string ToSql<TReturn>(Expression<Func<ISelectGroupingAggregate<T1>, TReturn>> select) {
 | 
			
		||||
			var map = new ReadAnonymousTypeInfo();
 | 
			
		||||
			var field = new StringBuilder();
 | 
			
		||||
			var index = 0;
 | 
			
		||||
 | 
			
		||||
			_comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString);
 | 
			
		||||
			var method = _select.GetType().GetMethod("ToSql", new[] { typeof(string) });
 | 
			
		||||
			return method.Invoke(_select, new object[] { map.Childs.Count > 0 ? field.Remove(0, 2).ToString() : null }) as string;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
		public abstract List<T1> ExecuteUpdated();
 | 
			
		||||
 | 
			
		||||
		public IUpdate<T1> IgnoreColumns(Expression<Func<T1, object>> columns) {
 | 
			
		||||
			var cols = _commonExpression.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(null, columns?.Body, false).Distinct();
 | 
			
		||||
			var cols = _commonExpression.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(null, columns?.Body, false, null).Distinct();
 | 
			
		||||
			_ignore.Clear();
 | 
			
		||||
			foreach (var col in cols) _ignore.Add(col, true);
 | 
			
		||||
			return this;
 | 
			
		||||
@@ -53,7 +53,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
		public IUpdate<T1> Set<TMember>(Expression<Func<T1, TMember>> column, TMember value) {
 | 
			
		||||
			var cols = new List<SelectColumnInfo>();
 | 
			
		||||
			_commonExpression.ExpressionSelectColumn_MemberAccess(null, cols, SelectTableInfoType.From, column?.Body, true);
 | 
			
		||||
			_commonExpression.ExpressionSelectColumn_MemberAccess(null, cols, SelectTableInfoType.From, column?.Body, true, null);
 | 
			
		||||
			if (cols.Count != 1) return this;
 | 
			
		||||
			var col = cols.First();
 | 
			
		||||
			_set.Append(", ").Append(_commonUtils.QuoteSqlName(col.Column.Attribute.Name)).Append(" = ").Append(_commonUtils.QuoteWriteParamter(col.Column.CsType, $"{_commonUtils.QuoteParamterName("p_")}{_params.Count}"));
 | 
			
		||||
@@ -64,7 +64,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
		public IUpdate<T1> Set<TMember>(Expression<Func<T1, TMember>> binaryExpression) {
 | 
			
		||||
			if (binaryExpression?.Body is BinaryExpression == false) return this;
 | 
			
		||||
			var cols = new List<SelectColumnInfo>();
 | 
			
		||||
			var expt = _commonExpression.ExpressionWhereLambdaNoneForeignObject(null, cols, binaryExpression);
 | 
			
		||||
			var expt = _commonExpression.ExpressionWhereLambdaNoneForeignObject(null, cols, binaryExpression, null);
 | 
			
		||||
			if (cols.Any() == false) return this;
 | 
			
		||||
			foreach (var col in cols) {
 | 
			
		||||
				if (col.Column.Attribute.IsNullable) {
 | 
			
		||||
@@ -84,7 +84,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
			return this;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public IUpdate<T1> Where(Expression<Func<T1, bool>> expression) => this.Where(_commonExpression.ExpressionWhereLambdaNoneForeignObject(null, null, expression?.Body));
 | 
			
		||||
		public IUpdate<T1> Where(Expression<Func<T1, bool>> expression) => this.Where(_commonExpression.ExpressionWhereLambdaNoneForeignObject(null, null, expression?.Body, null));
 | 
			
		||||
		public IUpdate<T1> Where(string sql, object parms = null) {
 | 
			
		||||
			if (string.IsNullOrEmpty(sql)) return this;
 | 
			
		||||
			_where.Append(" AND (").Append(sql).Append(")");
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@ namespace FreeSql.Internal {
 | 
			
		||||
 | 
			
		||||
		static ConcurrentDictionary<string, TableInfo> _cacheGetTableByEntity = new ConcurrentDictionary<string, TableInfo>();
 | 
			
		||||
		internal static TableInfo GetTableByEntity(Type entity, CommonUtils common) {
 | 
			
		||||
			if (entity.FullName.StartsWith("<>f__AnonymousType")) return null;
 | 
			
		||||
			if (_cacheGetTableByEntity.TryGetValue($"{common.QuoteSqlName("db")}{entity.FullName}", out var trytb)) return trytb; //区分数据库类型缓存
 | 
			
		||||
			if (common.CodeFirst.GetDbInfo(entity) != null) return null;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user