From d88b465022e70ced99b0c8d359f58d53a7ec4445 Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Tue, 3 Nov 2020 12:00:24 +0800 Subject: [PATCH] - debug code --- .../FreeSql.Extensions.Linq.csproj | 6 +- .../SelectedQueryProvider.cs | 175 ++++++++++++++++++ FreeSql/Internal/CommonExpression.cs | 96 +++++----- .../SelectProvider/SelectGroupingProvider.cs | 6 +- 4 files changed, 233 insertions(+), 50 deletions(-) create mode 100644 Extensions/FreeSql.Extensions.Linq/SelectedQueryProvider.cs diff --git a/Extensions/FreeSql.Extensions.Linq/FreeSql.Extensions.Linq.csproj b/Extensions/FreeSql.Extensions.Linq/FreeSql.Extensions.Linq.csproj index f3f175c5..f11ca82d 100644 --- a/Extensions/FreeSql.Extensions.Linq/FreeSql.Extensions.Linq.csproj +++ b/Extensions/FreeSql.Extensions.Linq/FreeSql.Extensions.Linq.csproj @@ -29,7 +29,11 @@ FreeSql.Extensions.Linq.xml 3 - + + + net40 + + diff --git a/Extensions/FreeSql.Extensions.Linq/SelectedQueryProvider.cs b/Extensions/FreeSql.Extensions.Linq/SelectedQueryProvider.cs new file mode 100644 index 00000000..8d58c3c9 --- /dev/null +++ b/Extensions/FreeSql.Extensions.Linq/SelectedQueryProvider.cs @@ -0,0 +1,175 @@ +using FreeSql.Internal.Model; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace FreeSql +{ + public interface ISelectedQuery + { +#if net40 +#else + Task> ToListAsync(); + Task ToOneAsync(); + Task FirstAsync(); + + Task AnyAsync(); + Task CountAsync(); +#endif + + List ToList(); + TOut ToOne(); + TOut First(); + + string ToSql(); + bool Any(); + + long Count(); + ISelectedQuery Count(out long count); + + ISelectedQuery Skip(int offset); + ISelectedQuery Offset(int offset); + ISelectedQuery Limit(int limit); + ISelectedQuery Take(int limit); + ISelectedQuery Page(int pageNumber, int pageSize); + + ISelectedQuery Where(Expression> exp); + ISelectedQuery WhereIf(bool condition, Expression> exp); + + ISelectedQuery OrderBy(Expression> column); + ISelectedQuery OrderByIf(bool condition, Expression> column, bool descending = false); + ISelectedQuery OrderByDescending(Expression> column); + } +} + +namespace FreeSql.Internal.CommonProvider +{ + public class SelectedQueryProvider : BaseDiyMemberExpression, ISelectedQuery + { + public Select0Provider _select; + public CommonExpression _comonExp; + public SelectedQueryProvider(Select0Provider select, Expression selector) + { + _select = select; + _comonExp = _select._commonExpression; + _map = new ReadAnonymousTypeInfo(); + var field = new StringBuilder(); + var index = -10000; //临时规则,不返回 as1 + + if (selector != null) + _comonExp.ReadAnonymousField(_select._tables, field, _map, ref index, selector, null, null, _select._whereGlobalFilter, null, false); //不走 DTO 映射,不处理 IncludeMany + _field = field.ToString(); + } + + public override string ParseExp(Expression[] members) + { + if (members.Any() == false) return _map.DbField; + 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; + } + +#if net40 +#else + public Task> ToListAsync() + { + var method = _select.GetType().GetMethod("ToListMapReaderAsync", BindingFlags.Instance | BindingFlags.NonPublic); + method = method.MakeGenericMethod(typeof(TOut)); + return method.Invoke(_select, new object[] { new ReadAnonymousTypeAfInfo(_map, _field.Length > 0 ? _field.Remove(0, 2).ToString() : null) }) as Task>; + } + async public Task ToOneAsync() => (await ToListAsync()).FirstOrDefault(); + public Task FirstAsync() => ToOneAsync(); + + public Task AnyAsync() + { + var method = _select.GetType().GetMethod("AnyAsync", new Type[0]); + return method.Invoke(_select, new object[0]) as Task; + } + public Task CountAsync() + { + var method = _select.GetType().GetMethod("CountAsync", new Type[0]); + return method.Invoke(_select, new object[0]) as Task; + } +#endif + + public List ToList() + { + var method = _select.GetType().GetMethod("ToListMapReader", BindingFlags.Instance | BindingFlags.NonPublic); + method = method.MakeGenericMethod(typeof(TOut)); + return method.Invoke(_select, new object[] { new ReadAnonymousTypeAfInfo(_map, _field.Length > 0 ? _field.Remove(0, 2).ToString() : null) }) as List; + } + public TOut ToOne() => ToList().FirstOrDefault(); + public TOut First() => ToOne(); + + public string ToSql() + { + var method = _select.GetType().GetMethod("ToSql", new[] { typeof(string) }); + return method.Invoke(_select, new object[] { _field.Length > 0 ? _field.Remove(0, 2).ToString() : null }) as string; + } + + public bool Any() + { + var method = _select.GetType().GetMethod("Any", new Type[0]); + return (bool)method.Invoke(_select, new object[0]); + } + public long Count() + { + var method = _select.GetType().GetMethod("Count", new Type[0]); + return (long)method.Invoke(_select, new object[0]); + } + public ISelectedQuery Count(out long count) + { + count = this.Count(); + return this; + } + + public ISelectedQuery Skip(int offset) + { + _select._skip = offset; + return this; + } + public ISelectedQuery Offset(int offset) => Skip(offset); + public ISelectedQuery Limit(int limit) => Take(limit); + public ISelectedQuery Take(int limit) + { + _select._limit = limit; + return this; + } + public ISelectedQuery Page(int pageNumber, int pageSize) + { + this.Skip(Math.Max(0, pageNumber - 1) * pageSize); + return this.Limit(pageSize); + } + + public ISelectedQuery OrderBy(Expression> column) => OrderByIf(true, column); + public ISelectedQuery OrderByIf(bool condition, Expression> column, bool descending = false) + { + if (condition == false) return this; + var sql = _comonExp.ExpressionWhereLambda(null, column, this, null, null); + var method = _select.GetType().GetMethod("OrderBy", new[] { typeof(string), typeof(object) }); + method.Invoke(_select, new object[] { descending ? $"{sql} DESC" : sql, null }); + return this; + } + public ISelectedQuery OrderByDescending(Expression> column) => OrderByIf(true, column, true); + + public ISelectedQuery Where(Expression> exp) => WhereIf(true, exp); + public ISelectedQuery WhereIf(bool condition, Expression> exp) + { + if (condition == false) return this; + var sql = _comonExp.ExpressionWhereLambda(null, exp, this, null, null); + var method = _select.GetType().GetMethod("Where", new[] { typeof(string), typeof(object) }); + method.Invoke(_select, new object[] { sql, null }); + return this; + } + } +} diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index 44df11aa..ca0880af 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -16,6 +16,13 @@ using System.Threading; namespace FreeSql.Internal { + public abstract class BaseDiyMemberExpression + { + public ReadAnonymousTypeInfo _map; + public string _field; + public abstract string ParseExp(Expression[] members); + } + public abstract class CommonExpression { @@ -28,13 +35,13 @@ namespace FreeSql.Internal } internal const int ReadAnonymousFieldAsCsName = -53129; - public bool ReadAnonymousField(List _tables, StringBuilder field, ReadAnonymousTypeInfo parent, ref int index, Expression exp, Select0Provider select, SelectGroupingProvider grouping, List whereGlobalFilter, List findIncludeMany, bool isAllDtoMap) + public bool ReadAnonymousField(List _tables, StringBuilder field, ReadAnonymousTypeInfo parent, ref int index, Expression exp, Select0Provider select, BaseDiyMemberExpression diymemexp, List whereGlobalFilter, List findIncludeMany, bool isAllDtoMap) { - Func getTSC = () => new ExpTSC { _tables = _tables, grouping = grouping, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, whereGlobalFilter = whereGlobalFilter, dbParams = select?._params }; //#462 添加 DbParams 解决 + Func getTSC = () => new ExpTSC { _tables = _tables, diymemexp = diymemexp, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, whereGlobalFilter = whereGlobalFilter, dbParams = select?._params }; //#462 添加 DbParams 解决 switch (exp.NodeType) { - case ExpressionType.Quote: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, select, grouping, whereGlobalFilter, findIncludeMany, isAllDtoMap); - case ExpressionType.Lambda: return ReadAnonymousField(_tables, field, parent, ref index, (exp as LambdaExpression)?.Body, select, grouping, whereGlobalFilter, findIncludeMany, isAllDtoMap); + case ExpressionType.Quote: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, select, diymemexp, whereGlobalFilter, findIncludeMany, isAllDtoMap); + case ExpressionType.Lambda: return ReadAnonymousField(_tables, field, parent, ref index, (exp as LambdaExpression)?.Body, select, diymemexp, whereGlobalFilter, findIncludeMany, isAllDtoMap); case ExpressionType.Negate: case ExpressionType.NegateChecked: parent.DbField = $"-({ExpressionLambdaToSql(exp, getTSC())})"; @@ -43,7 +50,7 @@ namespace FreeSql.Internal else if (index == ReadAnonymousFieldAsCsName && string.IsNullOrEmpty(parent.CsName) == false) field.Append(_common.FieldAsAlias(parent.CsName)); if (parent.CsType == null && exp.Type.IsValueType) parent.CsType = exp.Type; return false; - case ExpressionType.Convert: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, select, grouping, whereGlobalFilter, findIncludeMany, isAllDtoMap); + case ExpressionType.Convert: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, select, diymemexp, whereGlobalFilter, findIncludeMany, isAllDtoMap); case ExpressionType.Constant: var constExp = exp as ConstantExpression; //处理自定义SQL语句,如: ToList(new { @@ -93,7 +100,7 @@ namespace FreeSql.Internal { //加载表所有字段 var map = new List(); - ExpressionSelectColumn_MemberAccess(_tables, map, SelectTableInfoType.From, exp, true, grouping); + ExpressionSelectColumn_MemberAccess(_tables, map, SelectTableInfoType.From, exp, true, diymemexp); var tb = parent.Table = map.First().Table.Table; parent.CsType = tb.Type; parent.Consturctor = tb.Type.InternalGetTypeConstructor0OrFirst(); @@ -133,7 +140,7 @@ namespace FreeSql.Internal MapType = memProp.PropertyType }; parent.Childs.Add(child); - ReadAnonymousField(_tables, field, child, ref index, Expression.MakeMemberAccess(exp, memProp), select, grouping, whereGlobalFilter, findIncludeMany, false); + ReadAnonymousField(_tables, field, child, ref index, Expression.MakeMemberAccess(exp, memProp), select, diymemexp, whereGlobalFilter, findIncludeMany, false); } } } @@ -163,11 +170,11 @@ namespace FreeSql.Internal } } } - if (grouping != null && exp is MemberExpression expMem2 && expMem2.Member.Name == "Key" && expMem2.Expression.Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`")) + if (diymemexp != null && exp is MemberExpression expMem2 && expMem2.Member.Name == "Key" && expMem2.Expression.Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`")) { - field.Append(grouping._field); + field.Append(diymemexp._field); var parentProp = parent.Property; - grouping._map.CopyTo(parent); + diymemexp._map.CopyTo(parent); parent.Property = parentProp; //若不加此行,会引用 GroupBy(..).ToList(a => new Dto { key = a.Key }) null 错误,CopyTo 之后 Property 变为 null return false; } @@ -199,7 +206,7 @@ namespace FreeSql.Internal MapType = initExp.NewExpression.Arguments[a].Type }; parent.Childs.Add(child); - ReadAnonymousField(_tables, field, child, ref index, initExp.NewExpression.Arguments[a], select, grouping, whereGlobalFilter, findIncludeMany, false); + ReadAnonymousField(_tables, field, child, ref index, initExp.NewExpression.Arguments[a], select, diymemexp, whereGlobalFilter, findIncludeMany, false); } } else if (isAllDtoMap && _tables != null && _tables.Any() && initExp.NewExpression.Type != _tables.FirstOrDefault().Table.Type) @@ -224,7 +231,7 @@ namespace FreeSql.Internal }; parent.Childs.Add(child); if (dtTb.Parameter != null) - ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtTb.Parameter, dtTb.Table.Properties[trydtocol.CsName]), select, grouping, whereGlobalFilter, findIncludeMany, isAllDtoMap); + ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtTb.Parameter, dtTb.Table.Properties[trydtocol.CsName]), select, diymemexp, whereGlobalFilter, findIncludeMany, isAllDtoMap); else { child.DbField = $"{dtTb.Alias}.{_common.QuoteSqlName(trydtocol.Attribute.Name)}"; @@ -250,7 +257,7 @@ namespace FreeSql.Internal MapType = initAssignExp.Expression.Type }; parent.Childs.Add(child); - ReadAnonymousField(_tables, field, child, ref index, initAssignExp.Expression, select, grouping, whereGlobalFilter, findIncludeMany, false); + ReadAnonymousField(_tables, field, child, ref index, initAssignExp.Expression, select, diymemexp, whereGlobalFilter, findIncludeMany, false); } } if (parent.Childs.Any() == false) throw new Exception($"映射异常:{initExp.NewExpression.Type.Name} 没有一个属性名相同"); @@ -283,7 +290,7 @@ namespace FreeSql.Internal MapType = newExp.Arguments[a].Type }; parent.Childs.Add(child); - ReadAnonymousField(_tables, field, child, ref index, newExp.Arguments[a], select, grouping, whereGlobalFilter, findIncludeMany, false); + ReadAnonymousField(_tables, field, child, ref index, newExp.Arguments[a], select, diymemexp, whereGlobalFilter, findIncludeMany, false); } } else @@ -307,7 +314,7 @@ namespace FreeSql.Internal }; parent.Childs.Add(child); if (dtTb.Parameter != null) - ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtTb.Parameter, dtTb.Table.Properties[trydtocol.CsName]), select, grouping, whereGlobalFilter, findIncludeMany, isAllDtoMap); + ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtTb.Parameter, dtTb.Table.Properties[trydtocol.CsName]), select, diymemexp, whereGlobalFilter, findIncludeMany, isAllDtoMap); else { child.DbField = $"{dtTb.Alias}.{_common.QuoteSqlName(trydtocol.Attribute.Name)}"; @@ -404,32 +411,32 @@ namespace FreeSql.Internal return null; } - public string ExpressionSelectColumn_MemberAccess(List _tables, List _selectColumnMap, SelectTableInfoType tbtype, Expression exp, bool isQuoteName, SelectGroupingProvider grouping) + public string ExpressionSelectColumn_MemberAccess(List _tables, List _selectColumnMap, SelectTableInfoType tbtype, Expression exp, bool isQuoteName, BaseDiyMemberExpression diymemexp) { - return ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, _selectColumnMap = _selectColumnMap, grouping = grouping, tbtype = tbtype, isQuoteName = isQuoteName, isDisableDiyParse = false, style = ExpressionStyle.SelectColumns }); + return ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, _selectColumnMap = _selectColumnMap, diymemexp = diymemexp, tbtype = tbtype, isQuoteName = isQuoteName, isDisableDiyParse = false, style = ExpressionStyle.SelectColumns }); } - public string[] ExpressionSelectColumns_MemberAccess_New_NewArrayInit(List _tables, Expression exp, bool isQuoteName, SelectGroupingProvider grouping) + public string[] ExpressionSelectColumns_MemberAccess_New_NewArrayInit(List _tables, Expression exp, bool isQuoteName, BaseDiyMemberExpression diymemexp) { switch (exp?.NodeType) { - case ExpressionType.Quote: return ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, (exp as UnaryExpression)?.Operand, isQuoteName, grouping); - case ExpressionType.Lambda: return ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, (exp as LambdaExpression)?.Body, isQuoteName, grouping); - case ExpressionType.Convert: return ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, (exp as UnaryExpression)?.Operand, isQuoteName, grouping); - case ExpressionType.Constant: return new[] { ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, isQuoteName, grouping) }; + case ExpressionType.Quote: return ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, (exp as UnaryExpression)?.Operand, isQuoteName, diymemexp); + case ExpressionType.Lambda: return ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, (exp as LambdaExpression)?.Body, isQuoteName, diymemexp); + case ExpressionType.Convert: return ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, (exp as UnaryExpression)?.Operand, isQuoteName, diymemexp); + case ExpressionType.Constant: return new[] { ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, isQuoteName, diymemexp) }; case ExpressionType.Call: - case ExpressionType.MemberAccess: return ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, isQuoteName, grouping).Trim('(', ')', '\'').Split(new[] { "','" }, StringSplitOptions.RemoveEmptyEntries); + case ExpressionType.MemberAccess: return ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, isQuoteName, diymemexp).Trim('(', ')', '\'').Split(new[] { "','" }, StringSplitOptions.RemoveEmptyEntries); 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, grouping); + for (var a = 0; a < newExpMembers.Length; a++) newExpMembers[a] = ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, newExp.Arguments[a], isQuoteName, diymemexp); return newExpMembers.Distinct().Select(a => a.Trim('\'')).ToArray(); case ExpressionType.NewArrayInit: var newArr = exp as NewArrayExpression; if (newArr == null) break; var newArrMembers = new List(); - foreach (var newArrExp in newArr.Expressions) newArrMembers.AddRange(ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, newArrExp, isQuoteName, grouping)); + foreach (var newArrExp in newArr.Expressions) newArrMembers.AddRange(ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, newArrExp, isQuoteName, diymemexp)); return newArrMembers.Distinct().Select(a => a.Trim('\'')).ToArray(); default: throw new ArgumentException($"无法解析表达式:{exp}"); } @@ -454,22 +461,22 @@ namespace FreeSql.Internal { ExpressionType.Equal, "=" }, }; - public string ExpressionWhereLambdaNoneForeignObject(List _tables, TableInfo table, List _selectColumnMap, Expression exp, SelectGroupingProvider groupingProvider, List dbParams) + public string ExpressionWhereLambdaNoneForeignObject(List _tables, TableInfo table, List _selectColumnMap, Expression exp, BaseDiyMemberExpression diymemexp, List dbParams) { - var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, _selectColumnMap = _selectColumnMap, grouping = groupingProvider, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, currentTable = table, dbParams = dbParams }); + var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, _selectColumnMap = _selectColumnMap, diymemexp = diymemexp, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, currentTable = table, dbParams = dbParams }); return GetBoolString(exp, sql); } - public string ExpressionWhereLambda(List _tables, Expression exp, SelectGroupingProvider groupingProvider, List whereGlobalFilter, List dbParams) + public string ExpressionWhereLambda(List _tables, Expression exp, BaseDiyMemberExpression diymemexp, List whereGlobalFilter, List dbParams) { - var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, grouping = groupingProvider, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, whereGlobalFilter = whereGlobalFilter, dbParams = dbParams }); + var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, diymemexp = diymemexp, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, whereGlobalFilter = whereGlobalFilter, dbParams = dbParams }); return GetBoolString(exp, sql); } static ConcurrentDictionary dicRegexAlias = new ConcurrentDictionary(); - public void ExpressionJoinLambda(List _tables, SelectTableInfoType tbtype, Expression exp, SelectGroupingProvider groupingProvider, List whereGlobalFilter) + public void ExpressionJoinLambda(List _tables, SelectTableInfoType tbtype, Expression exp, BaseDiyMemberExpression diymemexp, List whereGlobalFilter) { var tbidx = _tables.Count; - var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, grouping = groupingProvider, tbtype = tbtype, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, whereGlobalFilter = whereGlobalFilter }); + var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, diymemexp = diymemexp, tbtype = tbtype, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, whereGlobalFilter = whereGlobalFilter }); sql = GetBoolString(exp, sql); if (_tables.Count > tbidx) @@ -891,7 +898,7 @@ namespace FreeSql.Internal var testExecuteExp = asSelectParentExp; if (asSelectParentExp.NodeType == ExpressionType.Parameter) //执行leftjoin关联 testExecuteExp = Expression.Property(testExecuteExp, _common.GetTableByEntity(asSelectParentExp.Type).ColumnsByCs.First().Key); - var tsc2 = tsc.CloneSetselectColumnMapAndgroupingAndtbtype(new List(), tsc.grouping, SelectTableInfoType.LeftJoin); + var tsc2 = tsc.Clone_selectColumnMap_diymemexp_tbtype(new List(), tsc.diymemexp, SelectTableInfoType.LeftJoin); tsc2.isDisableDiyParse = true; tsc2.style = ExpressionStyle.AsSelect; asSelectSql = ExpressionLambdaToSql(testExecuteExp, tsc2); @@ -1253,13 +1260,12 @@ namespace FreeSql.Internal return formatSql(Expression.Lambda(exp).Compile().DynamicInvoke(), tsc.mapType, tsc.mapColumnTmp, tsc.dbParams); } if (callExp != null) return ExpressionLambdaToSql(callExp, tsc); - if (tsc.grouping != null && expStack.First().Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`")) + if (tsc.diymemexp != null) { - if (tsc.grouping != null) - { - var expText = tsc.grouping.GetSelectGroupingMapString(expStack.Where((a, b) => b >= 2).ToArray()); - if (string.IsNullOrEmpty(expText) == false) return expText; - } + var expStackFirst = expStack.First(); + var bidx = expStackFirst.Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`") ? 2 : 1; //.Key .Value + var expText = tsc.diymemexp.ParseExp(expStack.Where((a, b) => b >= bidx).ToArray()); + if (string.IsNullOrEmpty(expText) == false) return expText; } if (tsc._tables == null) @@ -1367,9 +1373,9 @@ namespace FreeSql.Internal if (find.Type == SelectTableInfoType.InnerJoin || find.Type == SelectTableInfoType.LeftJoin || find.Type == SelectTableInfoType.RightJoin) - find.On = ExpressionLambdaToSql(navCondExp, tsc.CloneSetselectColumnMapAndgroupingAndtbtype(null, null, find.Type)); + find.On = ExpressionLambdaToSql(navCondExp, tsc.Clone_selectColumnMap_diymemexp_tbtype(null, null, find.Type)); else - find.NavigateCondition = ExpressionLambdaToSql(navCondExp, tsc.CloneSetselectColumnMapAndgroupingAndtbtype(null, null, find.Type)); + find.NavigateCondition = ExpressionLambdaToSql(navCondExp, tsc.Clone_selectColumnMap_diymemexp_tbtype(null, null, find.Type)); } } } @@ -1515,7 +1521,7 @@ namespace FreeSql.Internal { public List _tables { get; set; } public List _selectColumnMap { get; set; } - public SelectGroupingProvider grouping { get; set; } + public BaseDiyMemberExpression diymemexp { get; set; } public Select0Provider subSelect001 { get; set; } //#405 Oracle within group(order by ..) public SelectTableInfoType tbtype { get; set; } public bool isQuoteName { get; set; } @@ -1556,13 +1562,13 @@ namespace FreeSql.Internal return old; } - public ExpTSC CloneSetselectColumnMapAndgroupingAndtbtype(List v1, SelectGroupingProvider v2, SelectTableInfoType v3) + public ExpTSC Clone_selectColumnMap_diymemexp_tbtype(List v1, BaseDiyMemberExpression v2, SelectTableInfoType v3) { return new ExpTSC { _tables = this._tables, _selectColumnMap = v1, - grouping = v2, + diymemexp = v2, tbtype = v3, isQuoteName = this.isQuoteName, isDisableDiyParse = this.isDisableDiyParse, @@ -1582,7 +1588,7 @@ namespace FreeSql.Internal { _tables = this._tables, _selectColumnMap = this._selectColumnMap, - grouping = this.grouping, + diymemexp = this.diymemexp, subSelect001 = this.subSelect001, tbtype = this.tbtype, isQuoteName = this.isQuoteName, @@ -1626,7 +1632,7 @@ namespace FreeSql.Internal ); var whereSql = ExpressionLambdaToSql(expExp.Body, new ExpTSC { _tables = isMultitb ? new List(new[] { tb }) : null, - _selectColumnMap = null, grouping = null, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, currentTable = tb.Table, alias001 = tb.Alias }); + _selectColumnMap = null, diymemexp = null, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, currentTable = tb.Table, alias001 = tb.Alias }); whereSql = GetBoolString(expExp.Body, whereSql); if (isEmpty == false) sb.Append(" AND "); diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs index 25694049..33299b9f 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs @@ -11,12 +11,10 @@ using System.Threading.Tasks; namespace FreeSql.Internal.CommonProvider { - public class SelectGroupingProvider + public class SelectGroupingProvider : BaseDiyMemberExpression { public IFreeSql _orm; public Select0Provider _select; - public ReadAnonymousTypeInfo _map; - public string _field; public CommonExpression _comonExp; public List _tables; @@ -30,7 +28,7 @@ namespace FreeSql.Internal.CommonProvider _tables = tables; } - public string GetSelectGroupingMapString(Expression[] members) + public override string ParseExp(Expression[] members) { if (members.Any() == false) return _map.DbField; var parentName = ((members.FirstOrDefault() as MemberExpression)?.Expression as MemberExpression)?.Member.Name;