From 7efe02f69cc0796478674c9b83250c607b763d78 Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Fri, 7 Aug 2020 00:00:39 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E4=BC=98=E5=8C=96=20GroupBy=20ToList=20?= =?UTF-8?q?=E4=B8=AD=E5=8F=AF=E4=BB=A5=E7=9B=B4=E6=8E=A5=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=20a.Key=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MySqlConnector/Curd/MySqlSelectTest.cs | 2 +- .../Dameng/Curd/DamengSelectTest.cs | 2 +- .../Default/Curd/OdbcSelectTest.cs | 2 +- .../KingbaseES/Curd/KingbaseESSelectTest.cs | 2 +- .../MySql/Curd/MySqlSelectTest.cs | 2 +- .../Oracle/Curd/OracleSelectTest.cs | 2 +- .../PostgreSQL/Curd/PostgreSQLSelectTest.cs | 2 +- .../SqlServer/Curd/SqlServerSelectTest.cs | 2 +- .../Dameng/Curd/DamengSelectTest.cs | 2 +- .../MsAccess/Curd/MsAccessSelectTest.cs | 2 +- .../MySql/Curd/MySqlSelectTest.cs | 2 +- .../Oracle/Curd/OracleSelectTest.cs | 2 +- .../PostgreSQL/Curd/PostgreSQLSelectTest.cs | 2 +- .../ShenTong/Curd/ShenTongSelectTest.cs | 2 +- .../SqlServer/Curd/SqlServerSelectTest.cs | 2 +- .../Sqlite/Curd/SqliteSelectTest.cs | 2 +- FreeSql.Tests/FreeSql.Tests/UnitTest1.cs | 2 +- FreeSql.Tests/FreeSql.Tests/UnitTest3.cs | 27 ++++++ FreeSql/Internal/CommonExpression.cs | 82 ++++++++++--------- .../SelectProvider/SelectGroupingProvider.cs | 14 ++-- .../Internal/Model/ReadAnonymousTypeInfo.cs | 14 ++++ 21 files changed, 109 insertions(+), 62 deletions(-) diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs index c9d9dc32..3ab5e820 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs @@ -866,7 +866,7 @@ namespace FreeSql.Tests.MySqlConnector { b.Key.Title, b.Key.yyyy, - + b.Key, cou = b.Count(), sum2 = b.Sum(b.Value.TypeGuid) }); diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs index a50acd5b..7d20cdcb 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs @@ -793,7 +793,7 @@ namespace FreeSql.Tests.Odbc.Dameng { b.Key.Title, b.Key.yyyy, - + b.Key, cou = b.Count(), sum2 = b.Sum(b.Value.TypeGuid) }); diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Default/Curd/OdbcSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Default/Curd/OdbcSelectTest.cs index 59c91446..1e44d9f8 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Default/Curd/OdbcSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Default/Curd/OdbcSelectTest.cs @@ -784,7 +784,7 @@ namespace FreeSql.Tests.Odbc.Default { b.Key.Title, b.Key.yyyy, - + b.Key, cou = b.Count(), sum2 = b.Sum(b.Value.TypeGuid) }); diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/KingbaseES/Curd/KingbaseESSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/KingbaseES/Curd/KingbaseESSelectTest.cs index 6abeb543..5839a06f 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/KingbaseES/Curd/KingbaseESSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/KingbaseES/Curd/KingbaseESSelectTest.cs @@ -758,7 +758,7 @@ namespace FreeSql.Tests.Odbc.KingbaseES { b.Key.Title, b.Key.yyyy, - + b.Key, cou = b.Count(), sum2 = b.Sum(b.Value.TypeGuid) }); diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs index d4a1cc95..b5752d54 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs @@ -877,7 +877,7 @@ namespace FreeSql.Tests.Odbc.MySql { b.Key.Title, b.Key.yyyy, - + b.Key, cou = b.Count(), sum2 = b.Sum(b.Value.TypeGuid) }); diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs index 5e18bcfc..e7c817c8 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs @@ -794,7 +794,7 @@ namespace FreeSql.Tests.Odbc.Oracle { b.Key.Title, b.Key.yyyy, - + b.Key, cou = b.Count(), sum2 = b.Sum(b.Value.TypeGuid) }); diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs index bccdf194..cd197462 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs @@ -854,7 +854,7 @@ namespace FreeSql.Tests.Odbc.PostgreSQL { b.Key.Title, b.Key.yyyy, - + b.Key, cou = b.Count(), sum2 = b.Sum(b.Value.TypeGuid) }); diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs index dcfcc65d..7d4f9edd 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs @@ -749,7 +749,7 @@ namespace FreeSql.Tests.Odbc.SqlServer { b.Key.Title, b.Key.yyyy, - + b.Key, cou = b.Count(), sum2 = b.Sum(b.Value.TypeGuid) }); diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs index 441fc1f9..5a824785 100644 --- a/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs @@ -793,7 +793,7 @@ namespace FreeSql.Tests.Dameng { b.Key.Title, b.Key.yyyy, - + b.Key, cou = b.Count(), sum2 = b.Sum(b.Value.TypeGuid) }); diff --git a/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs index 24c806a0..f1b932d9 100644 --- a/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs @@ -785,7 +785,7 @@ namespace FreeSql.Tests.MsAccess { b.Key.Title, b.Key.yyyy, - + b.Key, cou = b.Count(), sum2 = b.Sum(b.Value.TypeGuid) }); diff --git a/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs index 92eade33..64950b72 100644 --- a/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs @@ -913,7 +913,7 @@ namespace FreeSql.Tests.MySql { b.Key.Title, b.Key.yyyy, - + b.Key, cou = b.Count(), sum2 = b.Sum(b.Value.TypeGuid) }); diff --git a/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs index 4ec7bdc4..4b478551 100644 --- a/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs @@ -794,7 +794,7 @@ namespace FreeSql.Tests.Oracle { b.Key.Title, b.Key.yyyy, - + b.Key, cou = b.Count(), sum2 = b.Sum(b.Value.TypeGuid) }); diff --git a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs index 7cf806bd..472df22f 100644 --- a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs @@ -871,7 +871,7 @@ namespace FreeSql.Tests.PostgreSQL { b.Key.Title, b.Key.yyyy, - + b.Key, cou = b.Count(), sum2 = b.Sum(b.Value.TypeGuid) }); diff --git a/FreeSql.Tests/FreeSql.Tests/ShenTong/Curd/ShenTongSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/ShenTong/Curd/ShenTongSelectTest.cs index 07176067..39a32ff7 100644 --- a/FreeSql.Tests/FreeSql.Tests/ShenTong/Curd/ShenTongSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/ShenTong/Curd/ShenTongSelectTest.cs @@ -871,7 +871,7 @@ namespace FreeSql.Tests.ShenTong { b.Key.Title, b.Key.yyyy, - + b.Key, cou = b.Count(), sum2 = b.Sum(b.Value.TypeGuid) }); diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs index 429b64d9..03e49134 100644 --- a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs @@ -805,7 +805,7 @@ namespace FreeSql.Tests.SqlServer { b.Key.Title, b.Key.yyyy, - + b.Key, cou = b.Count(), sum2 = b.Sum(b.Value.TypeGuid) }); diff --git a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs index fe68188f..b13c6c65 100644 --- a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs @@ -759,7 +759,7 @@ namespace FreeSql.Tests.Sqlite { b.Key.Title, b.Key.yyyy, - + b.Key, cou = b.Count(), sum2 = b.Sum(b.Value.TypeGuid) }); diff --git a/FreeSql.Tests/FreeSql.Tests/UnitTest1.cs b/FreeSql.Tests/FreeSql.Tests/UnitTest1.cs index 48baf05b..81dd4ac7 100644 --- a/FreeSql.Tests/FreeSql.Tests/UnitTest1.cs +++ b/FreeSql.Tests/FreeSql.Tests/UnitTest1.cs @@ -996,7 +996,7 @@ namespace FreeSql.Tests { b.Key.Title, b.Key.yyyy, - + b.Key, cou = b.Count(), sum = b.Sum(b.Key.yyyy), sum2 = b.Sum(b.Value.TypeGuid) diff --git a/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs b/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs index 1f93eca1..167fda11 100644 --- a/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs +++ b/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs @@ -179,6 +179,17 @@ namespace FreeSql.Tests var aff2 = g.sqlite.Delete(10086).ExecuteAffrows(); Assert.Equal(aff1, aff2); + g.sqlserver.Delete().Where("1=1").ExecuteAffrows(); + g.sqlserver.Delete().Where("1=1").ExecuteAffrows(); + g.sqlserver.Insert(new[] { new Edi { Id = 1 }, new Edi { Id = 2 }, new Edi { Id = 3 }, new Edi { Id = 4 }, new Edi { Id = 5 } }).ExecuteAffrows(); + g.sqlserver.Insert(new[] { + new EdiItem { Id = 1, EdiId = 1 }, new EdiItem { Id = 2, EdiId = 1 }, new EdiItem { Id = 3, EdiId = 1 } , + new EdiItem { Id = 4, EdiId = 2 }, new EdiItem { Id = 5, EdiId = 2 }, + new EdiItem { Id = 6, EdiId = 3 }, new EdiItem { Id = 7, EdiId = 3 }, + new EdiItem { Id = 8, EdiId = 4 }, new EdiItem { Id = 9, EdiId = 4 }, + new EdiItem { Id = 10, EdiId = 5 }, new EdiItem { Id = 11, EdiId = 5 }, + }).ExecuteAffrows(); + var testStringFormat = g.sqlite.Select().First(a => new { str = $"x{a.Id}_{DateTime.Now.ToString("yyyyMM")}z", @@ -265,6 +276,22 @@ namespace FreeSql.Tests over1 = SqlExt.Rank().Over().OrderBy(a.Id).OrderByDescending(b.EdiId).ToValue(), }); + var sqlextCaseGroupBy1 = g.sqlserver.Select() + .InnerJoin((a, b) => b.Id == a.Id) + .GroupBy((a, b) => new { aid = a.Id, bid = b.Id }) + .ToDictionary(a => new + { + sum = a.Sum(a.Value.Item2.EdiId) + }); + + var sqlextCaseGroupBy2 = g.sqlserver.Select() + .InnerJoin((a, b) => b.Id == a.Id) + .GroupBy((a, b) => new { aid = a.Id, bid = b.Id }) + .ToList(a => new + { + a.Key, sum = a.Sum(a.Value.Item2.EdiId) + }); + var sqlextOver = g.sqlserver.Select() .InnerJoin((a, b) => b.Id == a.Id) diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index 1050d677..8c2132ef 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -28,13 +28,13 @@ namespace FreeSql.Internal } internal const int ReadAnonymousFieldAsCsName = -53129; - public bool ReadAnonymousField(List _tables, StringBuilder field, ReadAnonymousTypeInfo parent, ref int index, Expression exp, Func getSelectGroupingMapString, List whereCascadeExpression, bool isAllDtoMap) + public bool ReadAnonymousField(List _tables, StringBuilder field, ReadAnonymousTypeInfo parent, ref int index, Expression exp, SelectGroupingProvider grouping, List whereCascadeExpression, bool isAllDtoMap) { - Func getTSC = () => new ExpTSC { _tables = _tables, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, whereCascadeExpression = whereCascadeExpression }; + Func getTSC = () => new ExpTSC { _tables = _tables, grouping = grouping, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, whereCascadeExpression = whereCascadeExpression }; switch (exp.NodeType) { - case ExpressionType.Quote: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, getSelectGroupingMapString, whereCascadeExpression, isAllDtoMap); - case ExpressionType.Lambda: return ReadAnonymousField(_tables, field, parent, ref index, (exp as LambdaExpression)?.Body, getSelectGroupingMapString, whereCascadeExpression, isAllDtoMap); + case ExpressionType.Quote: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, grouping, whereCascadeExpression, isAllDtoMap); + case ExpressionType.Lambda: return ReadAnonymousField(_tables, field, parent, ref index, (exp as LambdaExpression)?.Body, grouping, whereCascadeExpression, isAllDtoMap); case ExpressionType.Negate: case ExpressionType.NegateChecked: parent.DbField = $"-({ExpressionLambdaToSql(exp, getTSC())})"; @@ -43,7 +43,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, getSelectGroupingMapString, whereCascadeExpression, isAllDtoMap); + case ExpressionType.Convert: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, grouping, whereCascadeExpression, isAllDtoMap); case ExpressionType.Constant: var constExp = exp as ConstantExpression; //处理自定义SQL语句,如: ToList(new { @@ -93,7 +93,7 @@ namespace FreeSql.Internal { //加载表所有字段 var map = new List(); - ExpressionSelectColumn_MemberAccess(_tables, map, SelectTableInfoType.From, exp, true, getSelectGroupingMapString); + ExpressionSelectColumn_MemberAccess(_tables, map, SelectTableInfoType.From, exp, true, grouping); var tb = parent.Table = map.First().Table.Table; parent.CsType = tb.Type; parent.Consturctor = tb.Type.InternalGetTypeConstructor0OrFirst(); @@ -115,6 +115,12 @@ namespace FreeSql.Internal } else { + if (grouping != null && exp is MemberExpression expMem2 && expMem2.Member.Name == "Key" && expMem2.Expression.Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`")) + { + field.Append(grouping._field); + grouping._map.CopyTo(parent); + return false; + } parent.CsType = exp.Type; parent.DbField = ExpressionLambdaToSql(exp, getTSC()); field.Append(", ").Append(parent.DbField); @@ -141,7 +147,7 @@ namespace FreeSql.Internal MapType = initExp.NewExpression.Arguments[a].Type }; parent.Childs.Add(child); - ReadAnonymousField(_tables, field, child, ref index, initExp.NewExpression.Arguments[a], getSelectGroupingMapString, whereCascadeExpression, false); + ReadAnonymousField(_tables, field, child, ref index, initExp.NewExpression.Arguments[a], grouping, whereCascadeExpression, false); } } else if (isAllDtoMap && _tables != null && _tables.Any() && initExp.NewExpression.Type != _tables.FirstOrDefault().Table.Type) @@ -164,7 +170,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]), getSelectGroupingMapString, whereCascadeExpression, isAllDtoMap); + ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtTb.Parameter, dtTb.Table.Properties[trydtocol.CsName]), grouping, whereCascadeExpression, isAllDtoMap); else { child.DbField = $"{dtTb.Alias}.{_common.QuoteSqlName(trydtocol.Attribute.Name)}"; @@ -190,7 +196,7 @@ namespace FreeSql.Internal MapType = initAssignExp.Expression.Type }; parent.Childs.Add(child); - ReadAnonymousField(_tables, field, child, ref index, initAssignExp.Expression, getSelectGroupingMapString, whereCascadeExpression, false); + ReadAnonymousField(_tables, field, child, ref index, initAssignExp.Expression, grouping, whereCascadeExpression, false); } } if (parent.Childs.Any() == false) throw new Exception($"映射异常:{initExp.NewExpression.Type.Name} 没有一个属性名相同"); @@ -223,7 +229,7 @@ namespace FreeSql.Internal MapType = newExp.Arguments[a].Type }; parent.Childs.Add(child); - ReadAnonymousField(_tables, field, child, ref index, newExp.Arguments[a], getSelectGroupingMapString, whereCascadeExpression, false); + ReadAnonymousField(_tables, field, child, ref index, newExp.Arguments[a], grouping, whereCascadeExpression, false); } } else @@ -247,7 +253,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]), getSelectGroupingMapString, whereCascadeExpression, isAllDtoMap); + ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtTb.Parameter, dtTb.Table.Properties[trydtocol.CsName]), grouping, whereCascadeExpression, isAllDtoMap); else { child.DbField = $"{dtTb.Alias}.{_common.QuoteSqlName(trydtocol.Attribute.Name)}"; @@ -339,32 +345,32 @@ namespace FreeSql.Internal return null; } - public string ExpressionSelectColumn_MemberAccess(List _tables, List _selectColumnMap, SelectTableInfoType tbtype, Expression exp, bool isQuoteName, Func getSelectGroupingMapString) + public string ExpressionSelectColumn_MemberAccess(List _tables, List _selectColumnMap, SelectTableInfoType tbtype, Expression exp, bool isQuoteName, SelectGroupingProvider grouping) { - return ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, _selectColumnMap = _selectColumnMap, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = tbtype, isQuoteName = isQuoteName, isDisableDiyParse = false, style = ExpressionStyle.SelectColumns }); + return ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, _selectColumnMap = _selectColumnMap, grouping = grouping, tbtype = tbtype, isQuoteName = isQuoteName, isDisableDiyParse = false, style = ExpressionStyle.SelectColumns }); } - public string[] ExpressionSelectColumns_MemberAccess_New_NewArrayInit(List _tables, Expression exp, bool isQuoteName, Func getSelectGroupingMapString) + public string[] ExpressionSelectColumns_MemberAccess_New_NewArrayInit(List _tables, Expression exp, bool isQuoteName, SelectGroupingProvider grouping) { switch (exp?.NodeType) { - 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.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.Call: - case ExpressionType.MemberAccess: return ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, isQuoteName, getSelectGroupingMapString).Trim('(', ')', '\'').Split(new[] { "','" }, StringSplitOptions.RemoveEmptyEntries); + case ExpressionType.MemberAccess: return ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, isQuoteName, grouping).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, getSelectGroupingMapString); + for (var a = 0; a < newExpMembers.Length; a++) newExpMembers[a] = ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, newExp.Arguments[a], isQuoteName, grouping); 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, getSelectGroupingMapString)); + foreach (var newArrExp in newArr.Expressions) newArrMembers.AddRange(ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, newArrExp, isQuoteName, grouping)); return newArrMembers.Distinct().Select(a => a.Trim('\'')).ToArray(); default: throw new ArgumentException($"无法解析表达式:{exp}"); } @@ -389,22 +395,22 @@ namespace FreeSql.Internal { ExpressionType.Equal, "=" }, }; - public string ExpressionWhereLambdaNoneForeignObject(List _tables, TableInfo table, List _selectColumnMap, Expression exp, Func getSelectGroupingMapString, List dbParams) + public string ExpressionWhereLambdaNoneForeignObject(List _tables, TableInfo table, List _selectColumnMap, Expression exp, SelectGroupingProvider groupingProvider, List dbParams) { - var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, _selectColumnMap = _selectColumnMap, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, currentTable = table, dbParams = 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 }); return GetBoolString(exp, sql); } - public string ExpressionWhereLambda(List _tables, Expression exp, Func getSelectGroupingMapString, List whereCascadeExpression, List dbParams) + public string ExpressionWhereLambda(List _tables, Expression exp, SelectGroupingProvider groupingProvider, List whereCascadeExpression, List dbParams) { - var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, whereCascadeExpression = whereCascadeExpression, dbParams = dbParams }); + var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, grouping = groupingProvider, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, whereCascadeExpression = whereCascadeExpression, dbParams = dbParams }); return GetBoolString(exp, sql); } static ConcurrentDictionary dicRegexAlias = new ConcurrentDictionary(); - public void ExpressionJoinLambda(List _tables, SelectTableInfoType tbtype, Expression exp, Func getSelectGroupingMapString, List whereCascadeExpression) + public void ExpressionJoinLambda(List _tables, SelectTableInfoType tbtype, Expression exp, SelectGroupingProvider groupingProvider, List whereCascadeExpression) { var tbidx = _tables.Count; - var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = tbtype, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, whereCascadeExpression = whereCascadeExpression }); + var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, grouping = groupingProvider, tbtype = tbtype, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, whereCascadeExpression = whereCascadeExpression }); sql = GetBoolString(exp, sql); if (_tables.Count > tbidx) @@ -813,7 +819,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.CloneSetgetSelectGroupingMapStringAndgetSelectGroupingMapStringAndtbtype(new List(), tsc.getSelectGroupingMapString, SelectTableInfoType.LeftJoin); + var tsc2 = tsc.CloneSetselectColumnMapAndgroupingAndtbtype(new List(), tsc.grouping, SelectTableInfoType.LeftJoin); tsc2.isDisableDiyParse = true; tsc2.style = ExpressionStyle.AsSelect; asSelectSql = ExpressionLambdaToSql(testExecuteExp, tsc2); @@ -1167,11 +1173,11 @@ 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.getSelectGroupingMapString != null && expStack.First().Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`")) + if (tsc.grouping != null && expStack.First().Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`")) { - if (tsc.getSelectGroupingMapString != null) + if (tsc.grouping != null) { - var expText = tsc.getSelectGroupingMapString(expStack.Where((a, b) => b >= 2).ToArray()); + var expText = tsc.grouping.GetSelectGroupingMapString(expStack.Where((a, b) => b >= 2).ToArray()); if (string.IsNullOrEmpty(expText) == false) return expText; } } @@ -1281,9 +1287,9 @@ namespace FreeSql.Internal if (find.Type == SelectTableInfoType.InnerJoin || find.Type == SelectTableInfoType.LeftJoin || find.Type == SelectTableInfoType.RightJoin) - find.On = ExpressionLambdaToSql(navCondExp, tsc.CloneSetgetSelectGroupingMapStringAndgetSelectGroupingMapStringAndtbtype(null, null, find.Type)); + find.On = ExpressionLambdaToSql(navCondExp, tsc.CloneSetselectColumnMapAndgroupingAndtbtype(null, null, find.Type)); else - find.NavigateCondition = ExpressionLambdaToSql(navCondExp, tsc.CloneSetgetSelectGroupingMapStringAndgetSelectGroupingMapStringAndtbtype(null, null, find.Type)); + find.NavigateCondition = ExpressionLambdaToSql(navCondExp, tsc.CloneSetselectColumnMapAndgroupingAndtbtype(null, null, find.Type)); } } } @@ -1429,7 +1435,7 @@ namespace FreeSql.Internal { public List _tables { get; set; } public List _selectColumnMap { get; set; } - public Func getSelectGroupingMapString { get; set; } + public SelectGroupingProvider grouping { get; set; } public SelectTableInfoType tbtype { get; set; } public bool isQuoteName { get; set; } public bool isDisableDiyParse { get; set; } @@ -1469,13 +1475,13 @@ namespace FreeSql.Internal return old; } - public ExpTSC CloneSetgetSelectGroupingMapStringAndgetSelectGroupingMapStringAndtbtype(List v1, Func v2, SelectTableInfoType v3) + public ExpTSC CloneSetselectColumnMapAndgroupingAndtbtype(List v1, SelectGroupingProvider v2, SelectTableInfoType v3) { return new ExpTSC { _tables = this._tables, _selectColumnMap = v1, - getSelectGroupingMapString = v2, + grouping = v2, tbtype = v3, isQuoteName = this.isQuoteName, isDisableDiyParse = this.isDisableDiyParse, @@ -1495,7 +1501,7 @@ namespace FreeSql.Internal { _tables = this._tables, _selectColumnMap = this._selectColumnMap, - getSelectGroupingMapString = this.getSelectGroupingMapString, + grouping = this.grouping, tbtype = this.tbtype, isQuoteName = this.isQuoteName, isDisableDiyParse = true, @@ -1537,7 +1543,7 @@ namespace FreeSql.Internal ); var whereSql = ExpressionLambdaToSql(expExp.Body, new ExpTSC { _tables = isMultitb ? new List(new[] { tb }) : null, - _selectColumnMap = null, getSelectGroupingMapString = null, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, currentTable = tb.Table, alias001 = tb.Alias }); + _selectColumnMap = null, grouping = 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 85f208d0..559befe1 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs @@ -30,7 +30,7 @@ namespace FreeSql.Internal.CommonProvider _tables = tables; } - public string getSelectGroupingMapString(Expression[] members) + public string GetSelectGroupingMapString(Expression[] members) { if (members.Any() == false) return _map.DbField; var parentName = ((members.FirstOrDefault() as MemberExpression)?.Expression as MemberExpression)?.Member.Name; @@ -90,13 +90,13 @@ namespace FreeSql.Internal.CommonProvider public void InternalHaving(Expression exp) { - var sql = _comonExp.ExpressionWhereLambda(null, exp, getSelectGroupingMapString, null, null); + var sql = _comonExp.ExpressionWhereLambda(null, exp, this, null, null); var method = _select.GetType().GetMethod("Having", new[] { typeof(string), typeof(object) }); method.Invoke(_select, new object[] { sql, null }); } public void InternalOrderBy(Expression exp, bool isDescending) { - var sql = _comonExp.ExpressionWhereLambda(null, exp, getSelectGroupingMapString, null, null); + var sql = _comonExp.ExpressionWhereLambda(null, exp, this, null, null); var method = _select.GetType().GetMethod("OrderBy", new[] { typeof(string), typeof(object) }); method.Invoke(_select, new object[] { isDescending ? $"{sql} DESC" : sql, null }); } @@ -106,7 +106,7 @@ namespace FreeSql.Internal.CommonProvider var field = new StringBuilder(); var index = 0; - _comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString, null, false); + _comonExp.ReadAnonymousField(null, field, map, ref index, select, this, null, false); if (map.Childs.Any() == false && map.MapType == null) map.MapType = elementType; var method = _select.GetType().GetMethod(isAsync ? "ToListMapReaderAsync" : "ToListMapReader", BindingFlags.Instance | BindingFlags.NonPublic); method = method.MakeGenericMethod(elementType); @@ -118,7 +118,7 @@ namespace FreeSql.Internal.CommonProvider var field = new StringBuilder(); var index = 0; - _comonExp.ReadAnonymousField(null, field, map, ref index, elementSelector, getSelectGroupingMapString, null, false); + _comonExp.ReadAnonymousField(null, field, map, ref index, elementSelector, this, null, false); if (map.Childs.Any() == false && map.MapType == null) map.MapType = elementType; var method = _select.GetType().GetMethod("ToListMapReaderPrivate", BindingFlags.Instance | BindingFlags.NonPublic); method = method.MakeGenericMethod(elementType); @@ -132,7 +132,7 @@ namespace FreeSql.Internal.CommonProvider var field = new StringBuilder(); var index = fieldAlias == FieldAliasOptions.AsProperty ? CommonExpression.ReadAnonymousFieldAsCsName : 0; - _comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString, null, false); + _comonExp.ReadAnonymousField(null, field, map, ref index, select, this, null, false); 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; } @@ -210,7 +210,7 @@ namespace FreeSql.Internal.CommonProvider var field = new StringBuilder(); var index = 0; - _comonExp.ReadAnonymousField(null, field, map, ref index, elementSelector, getSelectGroupingMapString, null, false); + _comonExp.ReadAnonymousField(null, field, map, ref index, elementSelector, this, null, false); if (map.Childs.Any() == false && map.MapType == null) map.MapType = typeof(TElement); var method = _select.GetType().GetMethod("ToListMapReaderPrivateAsync", BindingFlags.Instance | BindingFlags.NonPublic); method = method.MakeGenericMethod(typeof(TElement)); diff --git a/FreeSql/Internal/Model/ReadAnonymousTypeInfo.cs b/FreeSql/Internal/Model/ReadAnonymousTypeInfo.cs index f7018bc7..c782cf5b 100644 --- a/FreeSql/Internal/Model/ReadAnonymousTypeInfo.cs +++ b/FreeSql/Internal/Model/ReadAnonymousTypeInfo.cs @@ -17,6 +17,20 @@ namespace FreeSql.Internal.Model public TableInfo Table { get; set; } public bool IsEntity { get; set; } public bool IsDefaultCtor { get; set; } + + public void CopyTo(ReadAnonymousTypeInfo target) + { + target.Property = Property; + target.CsName = CsName; + target.CsType = CsType; + target.MapType = MapType; + target.DbField = DbField; + target.Consturctor = Consturctor; + target.Childs = Childs; + target.Table = Table; + target.IsEntity = IsEntity; + target.IsDefaultCtor = IsDefaultCtor; + } } public class ReadAnonymousTypeAfInfo {