From 02ab4949c0da3aae0508c347ff7dd904ac75602c Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Thu, 25 Apr 2019 12:34:09 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E4=BC=98=E5=8C=96=20ISelect.GroupBy=20?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=EF=BC=8C=E5=A2=9E=E5=8A=A0=20.Value=20?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E8=81=9A=E5=90=88=E6=BA=90=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=EF=BC=8CToList(a=20=3D>=20a.Sum(a.Value.Scor?= =?UTF-8?q?e))=EF=BC=9B=20-=20=E5=A2=9E=E5=8A=A0=20Expression=20string.Con?= =?UTF-8?q?cat=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs | 52 +++++++++++++ .../MySql/MySqlExpression/OtherTest.cs | 5 ++ FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs | 52 +++++++++++++ .../PostgreSQL/Curd/PostgreSQLSelectTest.cs | 47 +++++++++++ .../SqlServer/Curd/SqlServerSelectTest.cs | 47 +++++++++++ FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs | 52 +++++++++++++ FreeSql.Tests/UnitTest1.cs | 54 ++++++++++++- FreeSql/FreeSql.csproj | 2 +- FreeSql/Interface/Curd/ISelect/ISelect1.cs | 2 +- FreeSql/Interface/Curd/ISelect/ISelect10.cs | 2 +- FreeSql/Interface/Curd/ISelect/ISelect2.cs | 2 +- FreeSql/Interface/Curd/ISelect/ISelect3.cs | 2 +- FreeSql/Interface/Curd/ISelect/ISelect4.cs | 2 +- FreeSql/Interface/Curd/ISelect/ISelect5.cs | 2 +- FreeSql/Interface/Curd/ISelect/ISelect6.cs | 2 +- FreeSql/Interface/Curd/ISelect/ISelect7.cs | 2 +- FreeSql/Interface/Curd/ISelect/ISelect8.cs | 2 +- FreeSql/Interface/Curd/ISelect/ISelect9.cs | 2 +- .../Interface/Curd/ISelect/ISelectGrouping.cs | 34 ++++---- FreeSql/Internal/CommonExpression.cs | 4 +- .../SelectProvider/Select0Provider.cs | 4 +- .../SelectProvider/Select10Provider.cs | 6 +- .../SelectProvider/Select1Provider.cs | 6 +- .../SelectProvider/Select2Provider.cs | 6 +- .../SelectProvider/Select3Provider.cs | 6 +- .../SelectProvider/Select4Provider.cs | 6 +- .../SelectProvider/Select5Provider.cs | 6 +- .../SelectProvider/Select6Provider.cs | 6 +- .../SelectProvider/Select7Provider.cs | 6 +- .../SelectProvider/Select8Provider.cs | 6 +- .../SelectProvider/Select9Provider.cs | 6 +- .../SelectProvider/SelectGroupingProvider.cs | 77 ++++++++++++++----- FreeSql/Internal/CommonUtils.cs | 2 +- FreeSql/Internal/Model/SelectTableInfo.cs | 11 ++- FreeSql/MySql/MySqlExpression.cs | 4 +- FreeSql/MySql/MySqlUtils.cs | 3 +- FreeSql/Oracle/OracleExpression.cs | 2 + FreeSql/Oracle/OracleUtils.cs | 2 +- FreeSql/PostgreSQL/PostgreSQLExpression.cs | 2 + FreeSql/PostgreSQL/PostgreSQLUtils.cs | 2 +- FreeSql/SqlServer/SqlServerExpression.cs | 2 + FreeSql/SqlServer/SqlServerUtils.cs | 8 +- FreeSql/Sqlite/SqliteExpression.cs | 2 + FreeSql/Sqlite/SqliteUtils.cs | 2 +- 44 files changed, 466 insertions(+), 86 deletions(-) diff --git a/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs b/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs index 07f4b856..af8b32dd 100644 --- a/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs @@ -726,7 +726,59 @@ namespace FreeSql.Tests.MySql { arg1 = a.Avg(a.Key.mod4), ccc2 = a.Key.tt2 ?? "now()", //ccc = Convert.ToDateTime("now()"), partby = Convert.ToDecimal("sum(num) over(PARTITION BY server_id,os,rid,chn order by id desc)") + ccc3 = a.Max(a.Value.Item3.Id) }); + + var testpid1 = g.mysql.Insert().AppendData(new TestTypeInfo { Name = "Name" + DateTime.Now.ToString("yyyyMMddHHmmss") }).ExecuteIdentity(); + g.mysql.Insert().AppendData(new TestInfo { Title = "Title" + DateTime.Now.ToString("yyyyMMddHHmmss"), CreateTime = DateTime.Now, TypeGuid = (int)testpid1 }).ExecuteAffrows(); + + var aggsql1 = select + .GroupBy(a => a.Title) + .ToSql(b => new { + b.Key, + cou = b.Count(), + sum = b.Sum(b.Key), + sum2 = b.Sum(b.Value.TypeGuid) + }); + var aggtolist1 = select + .GroupBy(a => a.Title) + .ToList(b => new { + b.Key, + cou = b.Count(), + sum = b.Sum(b.Key), + sum2 = b.Sum(b.Value.TypeGuid) + }); + + var aggsql2 = select + .GroupBy(a => new { a.Title, yyyy = string.Concat(a.CreateTime.Year, '-', a.CreateTime.Month) }) + .ToSql(b => new { + b.Key.Title, + b.Key.yyyy, + + cou = b.Count(), + sum = b.Sum(b.Key.yyyy), + sum2 = b.Sum(b.Value.TypeGuid) + }); + var aggtolist2 = select + .GroupBy(a => new { a.Title, yyyy = string.Concat(a.CreateTime.Year, '-', a.CreateTime.Month) }) + .ToList(b => new { + b.Key.Title, + b.Key.yyyy, + + cou = b.Count(), + sum = b.Sum(b.Key.yyyy), + sum2 = b.Sum(b.Value.TypeGuid) + }); + + var aggsql3 = select + .GroupBy(a => a.Title) + .ToSql(b => new { + b.Key, + cou = b.Count(), + sum = b.Sum(b.Key), + sum2 = b.Sum(b.Value.TypeGuid), + sum3 = b.Sum(b.Value.Type.Parent.Id) + }); } [Fact] public void ToAggregate() { diff --git a/FreeSql.Tests/MySql/MySqlExpression/OtherTest.cs b/FreeSql.Tests/MySql/MySqlExpression/OtherTest.cs index 2eda55a7..ece900da 100644 --- a/FreeSql.Tests/MySql/MySqlExpression/OtherTest.cs +++ b/FreeSql.Tests/MySql/MySqlExpression/OtherTest.cs @@ -1,4 +1,5 @@ using FreeSql.DataAnnotations; +using MySql.Data.MySqlClient; using System; using System.Collections.Generic; using System.Linq; @@ -16,6 +17,10 @@ namespace FreeSql.Tests.MySqlExpression { [Fact] public void Array() { + int[] nullarr = null; + Assert.Throws(() => { select.Where(a => nullarr.Contains(a.testFieldInt)).ToList(); }); + Assert.Throws(() => { select.Where(a => new int[0].Contains(a.testFieldInt)).ToList(); }); + //in not in var sql111 = select.Where(a => new[] { 1, 2, 3 }.Contains(a.testFieldInt)).ToList(); var sql112 = select.Where(a => new[] { 1, 2, 3 }.Contains(a.testFieldInt) == false).ToList(); diff --git a/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs b/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs index 555603c8..9a203f92 100644 --- a/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs +++ b/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs @@ -622,7 +622,59 @@ namespace FreeSql.Tests.Oracle { arg1 = a.Avg(a.Key.mod4), ccc2 = a.Key.tt2 ?? "now()", //ccc = Convert.ToDateTime("now()"), partby = Convert.ToDecimal("sum(num) over(PARTITION BY server_id,os,rid,chn order by id desc)") + ccc3 = a.Max(a.Value.Item3.Id) }); + + var testpid1 = g.oracle.Insert().AppendData(new TestTypeInfo { Name = "Name" + DateTime.Now.ToString("yyyyMMddHHmmss") }).ExecuteIdentity(); + g.oracle.Insert().AppendData(new TestInfo { Title = "Title" + DateTime.Now.ToString("yyyyMMddHHmmss"), CreateTime = DateTime.Now, TypeGuid = (int)testpid1 }).ExecuteAffrows(); + + var aggsql1 = select + .GroupBy(a => a.Title) + .ToSql(b => new { + b.Key, + cou = b.Count(), + sum = b.Sum(b.Key), + sum2 = b.Sum(b.Value.TypeGuid) + }); + var aggtolist1 = select + .GroupBy(a => a.Title) + .ToList(b => new { + b.Key, + cou = b.Count(), + sum = b.Sum(b.Key), + sum2 = b.Sum(b.Value.TypeGuid) + }); + + var aggsql2 = select + .GroupBy(a => new { a.Title, yyyy = string.Concat(a.CreateTime.Year, '-', a.CreateTime.Month) }) + .ToSql(b => new { + b.Key.Title, + b.Key.yyyy, + + cou = b.Count(), + sum = b.Sum(b.Key.yyyy), + sum2 = b.Sum(b.Value.TypeGuid) + }); + var aggtolist2 = select + .GroupBy(a => new { a.Title, yyyy = string.Concat(a.CreateTime.Year, '-', a.CreateTime.Month) }) + .ToList(b => new { + b.Key.Title, + b.Key.yyyy, + + cou = b.Count(), + sum = b.Sum(b.Key.yyyy), + sum2 = b.Sum(b.Value.TypeGuid) + }); + + var aggsql3 = select + .GroupBy(a => a.Title) + .ToSql(b => new { + b.Key, + cou = b.Count(), + sum = b.Sum(b.Key), + sum2 = b.Sum(b.Value.TypeGuid), + sum3 = b.Sum(b.Value.Type.Parent.Id) + }); } [Fact] public void ToAggregate() { diff --git a/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs b/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs index 546f1a9f..e8004c49 100644 --- a/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs +++ b/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs @@ -693,7 +693,54 @@ namespace FreeSql.Tests.PostgreSQL { arg1 = a.Avg(a.Key.mod4), ccc2 = a.Key.tt2 ?? "now()", //ccc = Convert.ToDateTime("now()"), partby = Convert.ToDecimal("sum(num) over(PARTITION BY server_id,os,rid,chn order by id desc)") + ccc3 = a.Max(a.Value.Item3.Id) }); + + var testpid1 = g.pgsql.Insert().AppendData(new TestTypeInfo { Name = "Name" + DateTime.Now.ToString("yyyyMMddHHmmss") }).ExecuteIdentity(); + g.pgsql.Insert().AppendData(new TestInfo { Title = "Title" + DateTime.Now.ToString("yyyyMMddHHmmss"), CreateTime = DateTime.Now, TypeGuid = (int)testpid1 }).ExecuteAffrows(); + + var aggsql1 = select + .GroupBy(a => a.Title) + .ToSql(b => new { + b.Key, + cou = b.Count(), + sum2 = b.Sum(b.Value.TypeGuid) + }); + var aggtolist1 = select + .GroupBy(a => a.Title) + .ToList(b => new { + b.Key, + cou = b.Count(), + sum2 = b.Sum(b.Value.TypeGuid) + }); + + var aggsql2 = select + .GroupBy(a => new { a.Title, yyyy = string.Concat(a.CreateTime.Year, '-', a.CreateTime.Month) }) + .ToSql(b => new { + b.Key.Title, + b.Key.yyyy, + + cou = b.Count(), + sum2 = b.Sum(b.Value.TypeGuid) + }); + var aggtolist2 = select + .GroupBy(a => new { a.Title, yyyy = string.Concat(a.CreateTime.Year, '-', a.CreateTime.Month) }) + .ToList(b => new { + b.Key.Title, + b.Key.yyyy, + + cou = b.Count(), + sum2 = b.Sum(b.Value.TypeGuid) + }); + + var aggsql3 = select + .GroupBy(a => a.Title) + .ToSql(b => new { + b.Key, + cou = b.Count(), + sum2 = b.Sum(b.Value.TypeGuid), + sum3 = b.Sum(b.Value.Type.Parent.Id) + }); } [Fact] public void ToAggregate() { diff --git a/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs b/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs index c9e54380..b5ec7ef9 100644 --- a/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs +++ b/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs @@ -624,7 +624,54 @@ namespace FreeSql.Tests.SqlServer { arg1 = a.Avg(a.Key.mod4), ccc2 = a.Key.tt2 ?? "now()", //ccc = Convert.ToDateTime("now()"), partby = Convert.ToDecimal("sum(num) over(PARTITION BY server_id,os,rid,chn order by id desc)") + ccc3 = a.Max(a.Value.Item3.Id) }); + + var testpid1 = _sqlserverFixture.SqlServer.Insert().AppendData(new TestTypeInfo { Name = "Name" + DateTime.Now.ToString("yyyyMMddHHmmss") }).ExecuteIdentity(); + _sqlserverFixture.SqlServer.Insert().AppendData(new TestInfo { Title = "Title" + DateTime.Now.ToString("yyyyMMddHHmmss"), CreateTime = DateTime.Now, TypeGuid = (int)testpid1 }).ExecuteAffrows(); + + var aggsql1 = select + .GroupBy(a => a.Title) + .ToSql(b => new { + b.Key, + cou = b.Count(), + sum2 = b.Sum(b.Value.TypeGuid) + }); + var aggtolist1 = select + .GroupBy(a => a.Title) + .ToList(b => new { + b.Key, + cou = b.Count(), + sum2 = b.Sum(b.Value.TypeGuid) + }); + + var aggsql2 = select + .GroupBy(a => new { a.Title, yyyy = string.Concat(a.CreateTime.Year, '-', a.CreateTime.Month) }) + .ToSql(b => new { + b.Key.Title, + b.Key.yyyy, + + cou = b.Count(), + sum2 = b.Sum(b.Value.TypeGuid) + }); + var aggtolist2 = select + .GroupBy(a => new { a.Title, yyyy = string.Concat(a.CreateTime.Year, '-', a.CreateTime.Month) }) + .ToList(b => new { + b.Key.Title, + b.Key.yyyy, + + cou = b.Count(), + sum2 = b.Sum(b.Value.TypeGuid) + }); + + var aggsql3 = select + .GroupBy(a => a.Title) + .ToSql(b => new { + b.Key, + cou = b.Count(), + sum2 = b.Sum(b.Value.TypeGuid), + sum3 = b.Sum(b.Value.Type.Parent.Id) + }); } [Fact] public void ToAggregate() { diff --git a/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs b/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs index 986e1ef0..5b890e49 100644 --- a/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs +++ b/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs @@ -568,7 +568,59 @@ namespace FreeSql.Tests.Sqlite { arg1 = a.Avg(a.Key.mod4), ccc2 = a.Key.tt2 ?? "now()", //ccc = Convert.ToDateTime("now()"), partby = Convert.ToDecimal("sum(num) over(PARTITION BY server_id,os,rid,chn order by id desc)") + ccc3 = a.Max(a.Value.Item3.Id) }); + + var testpid1 = g.sqlite.Insert().AppendData(new TestTypeInfo { Name = "Name" + DateTime.Now.ToString("yyyyMMddHHmmss") }).ExecuteIdentity(); + g.sqlite.Insert().AppendData(new TestInfo { Title = "Title" + DateTime.Now.ToString("yyyyMMddHHmmss"), CreateTime = DateTime.Now, TypeGuid = (int)testpid1 }).ExecuteAffrows(); + + var aggsql1 = select + .GroupBy(a => a.Title) + .ToSql(b => new { + b.Key, + cou = b.Count(), + sum = b.Sum(b.Key), + sum2 = b.Sum(b.Value.TypeGuid) + }); + var aggtolist1 = select + .GroupBy(a => a.Title) + .ToList(b => new { + b.Key, + cou = b.Count(), + sum = b.Sum(b.Key), + sum2 = b.Sum(b.Value.TypeGuid) + }); + + var aggsql2 = select + .GroupBy(a => new { a.Title, yyyy = string.Concat(a.CreateTime.Year, '-', a.CreateTime.Month) }) + .ToSql(b => new { + b.Key.Title, + b.Key.yyyy, + + cou = b.Count(), + sum = b.Sum(b.Key.yyyy), + sum2 = b.Sum(b.Value.TypeGuid) + }); + var aggtolist2 = select + .GroupBy(a => new { a.Title, yyyy = string.Concat(a.CreateTime.Year, '-', a.CreateTime.Month) }) + .ToList(b => new { + b.Key.Title, + b.Key.yyyy, + + cou = b.Count(), + sum = b.Sum(b.Key.yyyy), + sum2 = b.Sum(b.Value.TypeGuid) + }); + + var aggsql3 = select + .GroupBy(a => a.Title) + .ToSql(b => new { + b.Key, + cou = b.Count(), + sum = b.Sum(b.Key), + sum2 = b.Sum(b.Value.TypeGuid), + sum3 = b.Sum(b.Value.Type.Parent.Id) + }); } [Fact] public void ToAggregate() { diff --git a/FreeSql.Tests/UnitTest1.cs b/FreeSql.Tests/UnitTest1.cs index 12349313..36846f63 100644 --- a/FreeSql.Tests/UnitTest1.cs +++ b/FreeSql.Tests/UnitTest1.cs @@ -53,6 +53,56 @@ namespace FreeSql.Tests { [Fact] public void Test1() { + var testpid1 = g.mysql.Insert().AppendData(new TestTypeInfo { Name = "Name" + DateTime.Now.ToString("yyyyMMddHHmmss") }).ExecuteIdentity(); + g.mysql.Insert().AppendData(new TestInfo { Title = "Title" + DateTime.Now.ToString("yyyyMMddHHmmss"), CreateTime = DateTime.Now, TypeGuid = (int)testpid1 }).ExecuteAffrows(); + + var aggsql1 = select + .GroupBy(a => a.Title) + .ToSql(b => new { + b.Key, + cou = b.Count(), + sum = b.Sum(b.Key), + sum2 = b.Sum(b.Value.TypeGuid) + }); + var aggtolist1 = select + .GroupBy(a => a.Title) + .ToList(b => new { + b.Key, + cou = b.Count(), + sum = b.Sum(b.Key), + sum2 = b.Sum(b.Value.TypeGuid) + }); + + var aggsql2 = select + .GroupBy(a => new { a.Title, yyyy = string.Concat(a.CreateTime.Year, '-', a.CreateTime.Month) }) + .ToSql(b => new { + b.Key.Title, + b.Key.yyyy, + + cou = b.Count(), + sum = b.Sum(b.Key.yyyy), + sum2 = b.Sum(b.Value.TypeGuid) + }); + var aggtolist2 = select + .GroupBy(a => new { a.Title, yyyy = string.Concat(a.CreateTime.Year, '-', a.CreateTime.Month) }) + .ToList(b => new { + b.Key.Title, + b.Key.yyyy, + + cou = b.Count(), + sum = b.Sum(b.Key.yyyy), + sum2 = b.Sum(b.Value.TypeGuid) + }); + + var aggsql3 = select + .GroupBy(a => a.Title) + .ToSql(b => new { + b.Key, + cou = b.Count(), + sum = b.Sum(b.Key), + sum2 = b.Sum(b.Value.TypeGuid), + sum3 = b.Sum(b.Value.Type.Parent.Parent.Id) + }); var sqlrepos = g.sqlite.GetRepository(); sqlrepos.Insert(new TestTypeParentInfo { @@ -201,7 +251,9 @@ namespace FreeSql.Tests { .Having(a => a.Count() > 0 && a.Avg(a.Key.mod4) > 0 && a.Max(a.Key.mod4) > 0) .Having(a => a.Count() < 300 || a.Avg(a.Key.mod4) < 100) .OrderBy(a => a.Key.tt2) - .OrderByDescending(a => a.Count()).ToSql(a => new { a.Key.mod4, a.Key.tt2, max = a.Max("a.id"), max2 = Convert.ToInt64("max(a.id)") }); + .OrderByDescending(a => a.Count()).ToSql(a => new { + cou = a.Sum(a.Value.Item1.Id), + a.Key.mod4, a.Key.tt2, max = a.Max("a.id"), max2 = Convert.ToInt64("max(a.id)") }); var groupbysql2 = g.mysql.Select().From((s, b, c) => s .Where(a => a.Id == 1) diff --git a/FreeSql/FreeSql.csproj b/FreeSql/FreeSql.csproj index eb1f25ac..a52bda67 100644 --- a/FreeSql/FreeSql.csproj +++ b/FreeSql/FreeSql.csproj @@ -2,7 +2,7 @@ netstandard2.0 - 0.5.4 + 0.5.4.1 true YeXiangQin FreeSql is the most convenient ORM in dotnet. It supports Mysql, Postgresql, SqlServer, Oracle and Sqlite. diff --git a/FreeSql/Interface/Curd/ISelect/ISelect1.cs b/FreeSql/Interface/Curd/ISelect/ISelect1.cs index afa80216..5ad7b3b8 100644 --- a/FreeSql/Interface/Curd/ISelect/ISelect1.cs +++ b/FreeSql/Interface/Curd/ISelect/ISelect1.cs @@ -271,7 +271,7 @@ namespace FreeSql { /// /// /// - ISelectGrouping GroupBy(Expression> exp); + ISelectGrouping GroupBy(Expression> exp); /// /// 按列排序,OrderBy(a => a.Time) diff --git a/FreeSql/Interface/Curd/ISelect/ISelect10.cs b/FreeSql/Interface/Curd/ISelect/ISelect10.cs index cf51ead7..8f2f7d5b 100644 --- a/FreeSql/Interface/Curd/ISelect/ISelect10.cs +++ b/FreeSql/Interface/Curd/ISelect/ISelect10.cs @@ -32,7 +32,7 @@ namespace FreeSql { ISelect Where(Expression> exp); ISelect WhereIf(bool condition, Expression> exp); - ISelectGrouping GroupBy(Expression> exp); + ISelectGrouping GroupBy(Expression> exp); ISelect OrderBy(Expression> column); ISelect OrderByDescending(Expression> column); diff --git a/FreeSql/Interface/Curd/ISelect/ISelect2.cs b/FreeSql/Interface/Curd/ISelect/ISelect2.cs index 3ea773b6..aff7f5e2 100644 --- a/FreeSql/Interface/Curd/ISelect/ISelect2.cs +++ b/FreeSql/Interface/Curd/ISelect/ISelect2.cs @@ -32,7 +32,7 @@ namespace FreeSql { ISelect Where(Expression> exp); ISelect WhereIf(bool condition, Expression> exp); - ISelectGrouping GroupBy(Expression> exp); + ISelectGrouping GroupBy(Expression> exp); ISelect OrderBy(Expression> column); ISelect OrderByDescending(Expression> column); diff --git a/FreeSql/Interface/Curd/ISelect/ISelect3.cs b/FreeSql/Interface/Curd/ISelect/ISelect3.cs index f352a292..0d965e21 100644 --- a/FreeSql/Interface/Curd/ISelect/ISelect3.cs +++ b/FreeSql/Interface/Curd/ISelect/ISelect3.cs @@ -32,7 +32,7 @@ namespace FreeSql { ISelect Where(Expression> exp); ISelect WhereIf(bool condition, Expression> exp); - ISelectGrouping GroupBy(Expression> exp); + ISelectGrouping GroupBy(Expression> exp); ISelect OrderBy(Expression> column); ISelect OrderByDescending(Expression> column); diff --git a/FreeSql/Interface/Curd/ISelect/ISelect4.cs b/FreeSql/Interface/Curd/ISelect/ISelect4.cs index b7fa9f75..d662d788 100644 --- a/FreeSql/Interface/Curd/ISelect/ISelect4.cs +++ b/FreeSql/Interface/Curd/ISelect/ISelect4.cs @@ -32,7 +32,7 @@ namespace FreeSql { ISelect Where(Expression> exp); ISelect WhereIf(bool condition, Expression> exp); - ISelectGrouping GroupBy(Expression> exp); + ISelectGrouping GroupBy(Expression> exp); ISelect OrderBy(Expression> column); ISelect OrderByDescending(Expression> column); diff --git a/FreeSql/Interface/Curd/ISelect/ISelect5.cs b/FreeSql/Interface/Curd/ISelect/ISelect5.cs index 68bceb4e..ffcf4294 100644 --- a/FreeSql/Interface/Curd/ISelect/ISelect5.cs +++ b/FreeSql/Interface/Curd/ISelect/ISelect5.cs @@ -32,7 +32,7 @@ namespace FreeSql { ISelect Where(Expression> exp); ISelect WhereIf(bool condition, Expression> exp); - ISelectGrouping GroupBy(Expression> exp); + ISelectGrouping GroupBy(Expression> exp); ISelect OrderBy(Expression> column); ISelect OrderByDescending(Expression> column); diff --git a/FreeSql/Interface/Curd/ISelect/ISelect6.cs b/FreeSql/Interface/Curd/ISelect/ISelect6.cs index 02d1f656..30ebba85 100644 --- a/FreeSql/Interface/Curd/ISelect/ISelect6.cs +++ b/FreeSql/Interface/Curd/ISelect/ISelect6.cs @@ -32,7 +32,7 @@ namespace FreeSql { ISelect Where(Expression> exp); ISelect WhereIf(bool condition, Expression> exp); - ISelectGrouping GroupBy(Expression> exp); + ISelectGrouping GroupBy(Expression> exp); ISelect OrderBy(Expression> column); ISelect OrderByDescending(Expression> column); diff --git a/FreeSql/Interface/Curd/ISelect/ISelect7.cs b/FreeSql/Interface/Curd/ISelect/ISelect7.cs index d44c45a3..21631412 100644 --- a/FreeSql/Interface/Curd/ISelect/ISelect7.cs +++ b/FreeSql/Interface/Curd/ISelect/ISelect7.cs @@ -32,7 +32,7 @@ namespace FreeSql { ISelect Where(Expression> exp); ISelect WhereIf(bool condition, Expression> exp); - ISelectGrouping GroupBy(Expression> exp); + ISelectGrouping GroupBy(Expression> exp); ISelect OrderBy(Expression> column); ISelect OrderByDescending(Expression> column); diff --git a/FreeSql/Interface/Curd/ISelect/ISelect8.cs b/FreeSql/Interface/Curd/ISelect/ISelect8.cs index 39e0bf73..e30882f8 100644 --- a/FreeSql/Interface/Curd/ISelect/ISelect8.cs +++ b/FreeSql/Interface/Curd/ISelect/ISelect8.cs @@ -32,7 +32,7 @@ namespace FreeSql { ISelect Where(Expression> exp); ISelect WhereIf(bool condition, Expression> exp); - ISelectGrouping GroupBy(Expression> exp); + ISelectGrouping GroupBy(Expression> exp); ISelect OrderBy(Expression> column); ISelect OrderByDescending(Expression> column); diff --git a/FreeSql/Interface/Curd/ISelect/ISelect9.cs b/FreeSql/Interface/Curd/ISelect/ISelect9.cs index 9af6de2f..d3c827ca 100644 --- a/FreeSql/Interface/Curd/ISelect/ISelect9.cs +++ b/FreeSql/Interface/Curd/ISelect/ISelect9.cs @@ -32,7 +32,7 @@ namespace FreeSql { ISelect Where(Expression> exp); ISelect WhereIf(bool condition, Expression> exp); - ISelectGrouping GroupBy(Expression> exp); + ISelectGrouping GroupBy(Expression> exp); ISelect OrderBy(Expression> column); ISelect OrderByDescending(Expression> column); diff --git a/FreeSql/Interface/Curd/ISelect/ISelectGrouping.cs b/FreeSql/Interface/Curd/ISelect/ISelectGrouping.cs index c33ac859..59532332 100644 --- a/FreeSql/Interface/Curd/ISelect/ISelectGrouping.cs +++ b/FreeSql/Interface/Curd/ISelect/ISelectGrouping.cs @@ -5,13 +5,13 @@ using System.Text; using System.Threading.Tasks; namespace FreeSql { - public interface ISelectGrouping { + public interface ISelectGrouping { /// /// 按聚合条件过滤,Where(a => a.Count() > 10) /// /// lambda表达式 /// - ISelectGrouping Having(Expression, bool>> exp); + ISelectGrouping Having(Expression, bool>> exp); /// /// 按列排序,OrderBy(a => a.Time) @@ -19,13 +19,13 @@ namespace FreeSql { /// /// /// - ISelectGrouping OrderBy(Expression, TMember>> column); + ISelectGrouping OrderBy(Expression, TMember>> column); /// /// 按列倒向排序,OrderByDescending(a => a.Time) /// /// 列 /// - ISelectGrouping OrderByDescending(Expression, TMember>> column); + ISelectGrouping OrderByDescending(Expression, TMember>> column); /// /// 执行SQL查询,返回指定字段的记录,记录不存在时返回 Count 为 0 的列表 @@ -33,8 +33,8 @@ namespace FreeSql { /// 返回类型 /// 选择列 /// - List ToList(Expression, TReturn>> select); - Task> ToListAsync(Expression, TReturn>> select); + List ToList(Expression, TReturn>> select); + Task> ToListAsync(Expression, TReturn>> select); /// /// 返回即将执行的SQL语句 @@ -42,7 +42,7 @@ namespace FreeSql { /// 返回类型 /// 选择列 /// - string ToSql(Expression, TReturn>> select); + string ToSql(Expression, TReturn>> select); /// @@ -50,25 +50,25 @@ namespace FreeSql { /// /// /// - ISelectGrouping Skip(int offset); + ISelectGrouping Skip(int offset); /// /// 查询向后偏移行数 /// /// 行数 /// - ISelectGrouping Offset(int offset); + ISelectGrouping Offset(int offset); /// /// 查询多少条数据 /// /// /// - ISelectGrouping Limit(int limit); + ISelectGrouping Limit(int limit); /// /// 查询多少条数据 /// /// /// - ISelectGrouping Take(int limit); + ISelectGrouping Take(int limit); /// /// 分页 @@ -76,14 +76,14 @@ namespace FreeSql { /// 第几页 /// 每页多少 /// - ISelectGrouping Page(int pageIndex, int pageSize); + ISelectGrouping Page(int pageIndex, int pageSize); } - public interface ISelectGroupingAggregate { + public interface ISelectGroupingAggregate { /// /// 分组的数据 /// - T1 Key { get; set; } + TKey Key { get; set; } /// /// 记录总数 /// @@ -117,4 +117,10 @@ namespace FreeSql { /// T3 Min(T3 column); } + public interface ISelectGroupingAggregate : ISelectGroupingAggregate { + /// + /// 所有元素 + /// + TValue Value { get; set; } + } } diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index dff01dca..f023f2f4 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -726,7 +726,7 @@ namespace FreeSql.Internal { case ExpressionType.MemberAccess: var exp2Type = exp2.Type; - if (exp2Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`")) exp2Type = exp2Type.GenericTypeArguments.FirstOrDefault() ?? exp2.Type; + if (exp2Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`")) exp2Type = exp2Type.GenericTypeArguments.LastOrDefault() ?? exp2.Type; var tb2tmp = _common.GetTableByEntity(exp2Type); var mp2 = exp2 as MemberExpression; if (mp2?.Member.Name == "Key" && mp2.Expression.Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`")) continue; @@ -794,7 +794,7 @@ namespace FreeSql.Internal { left = tmp; } if (right == "NULL") tryoper = tryoper == "=" ? " IS " : " IS NOT "; - if (tryoper == "+" && (expBinary.Left.Type.FullName == "System.String" || expBinary.Right.Type.FullName == "System.String")) return _common.StringConcat(left, right, expBinary.Left.Type, expBinary.Right.Type); + if (tryoper == "+" && (expBinary.Left.Type.FullName == "System.String" || expBinary.Right.Type.FullName == "System.String")) return _common.StringConcat(new[] { left, right }, new[] { expBinary.Left.Type, expBinary.Right.Type }); if (tryoper == "%") return _common.Mod(left, right, expBinary.Left.Type, expBinary.Right.Type); if (_common._orm.Ado.DataType == DataType.MySql) { //处理c#变态enum convert, a.EnumType1 == Xxx.Xxx,被转成了 Convert(a.EnumType1, Int32) == 1 diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs index cd9753e9..bfeca942 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs @@ -679,14 +679,14 @@ namespace FreeSql.Internal.CommonProvider { protected TMember InternalSum(Expression exp) => this.ToList($"sum({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)})").FirstOrDefault(); async protected Task InternalSumAsync(Expression exp) => (await this.ToListAsync($"sum({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)})")).FirstOrDefault(); - protected ISelectGrouping InternalGroupBy(Expression columns) { + protected ISelectGrouping InternalGroupBy(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(field.Length > 0 ? field.Remove(0, 2).ToString() : null); - return new SelectGroupingProvider(this, map, _commonExpression); + return new SelectGroupingProvider(this, map, _commonExpression, _tables); } protected TSelect InternalJoin(Expression exp, SelectTableInfoType joinType) { _commonExpression.ExpressionJoinLambda(_tables, joinType, exp, null); diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select10Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select10Provider.cs index 953a223d..71adbbc1 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select10Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select10Provider.cs @@ -44,10 +44,10 @@ namespace FreeSql.Internal.CommonProvider { return this.InternalAvgAsync(column?.Body); } - ISelectGrouping ISelect.GroupBy(Expression> exp) { - if (exp == null) return this.InternalGroupBy(exp?.Body); + ISelectGrouping ISelect.GroupBy(Expression> exp) { + if (exp == null) return this.InternalGroupBy(exp?.Body); for (var a = 0; a < exp.Parameters.Count; a++) _tables[a].Parameter = exp.Parameters[a]; - return this.InternalGroupBy(exp?.Body); + return this.InternalGroupBy (exp?.Body); } TMember ISelect.Max(Expression> column) { diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs index 035790d8..feae7640 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs @@ -87,10 +87,10 @@ namespace FreeSql.Internal.CommonProvider { public abstract ISelect From(Expression, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression>> 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(_orm, _commonUtils, _commonExpression, null); Select0Provider, T1>.CopyData(this, ret, exp?.Parameters); return ret; } - public ISelectGrouping GroupBy(Expression> columns) { - if (columns == null) return this.InternalGroupBy(columns); + public ISelectGrouping GroupBy(Expression> columns) { + if (columns == null) return this.InternalGroupBy(columns); _tables[0].Parameter = columns.Parameters[0]; - return this.InternalGroupBy(columns); + return this.InternalGroupBy(columns); } public TMember Max(Expression> column) { diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select2Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select2Provider.cs index 1c885e06..21b124a3 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select2Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select2Provider.cs @@ -28,10 +28,10 @@ namespace FreeSql.Internal.CommonProvider { return this.InternalAvgAsync(column?.Body); } - ISelectGrouping ISelect.GroupBy(Expression> exp) { - if (exp == null) return this.InternalGroupBy(exp?.Body); + ISelectGrouping ISelect.GroupBy(Expression> exp) { + if (exp == null) return this.InternalGroupBy(exp?.Body); for (var a = 0; a < exp.Parameters.Count; a++) _tables[a].Parameter = exp.Parameters[a]; - return this.InternalGroupBy(exp?.Body); + return this.InternalGroupBy(exp?.Body); } TMember ISelect.Max(Expression> column) { diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select3Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select3Provider.cs index d9013e58..add6d4bf 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select3Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select3Provider.cs @@ -30,10 +30,10 @@ namespace FreeSql.Internal.CommonProvider { return this.InternalAvgAsync(column?.Body); } - ISelectGrouping ISelect.GroupBy(Expression> exp) { - if (exp == null) return this.InternalGroupBy(exp?.Body); + ISelectGrouping ISelect.GroupBy(Expression> exp) { + if (exp == null) return this.InternalGroupBy(exp?.Body); for (var a = 0; a < exp.Parameters.Count; a++) _tables[a].Parameter = exp.Parameters[a]; - return this.InternalGroupBy(exp?.Body); + return this.InternalGroupBy(exp?.Body); } TMember ISelect.Max(Expression> column) { diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select4Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select4Provider.cs index 8fb84394..358015ad 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select4Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select4Provider.cs @@ -32,10 +32,10 @@ namespace FreeSql.Internal.CommonProvider { return this.InternalAvgAsync(column?.Body); } - ISelectGrouping ISelect.GroupBy(Expression> exp) { - if (exp == null) return this.InternalGroupBy(exp?.Body); + ISelectGrouping ISelect.GroupBy(Expression> exp) { + if (exp == null) return this.InternalGroupBy(exp?.Body); for (var a = 0; a < exp.Parameters.Count; a++) _tables[a].Parameter = exp.Parameters[a]; - return this.InternalGroupBy(exp?.Body); + return this.InternalGroupBy(exp?.Body); } TMember ISelect.Max(Expression> column) { diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select5Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select5Provider.cs index b4a50cad..c42d5e59 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select5Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select5Provider.cs @@ -34,10 +34,10 @@ namespace FreeSql.Internal.CommonProvider { return this.InternalAvgAsync(column?.Body); } - ISelectGrouping ISelect.GroupBy(Expression> exp) { - if (exp == null) return this.InternalGroupBy(exp?.Body); + ISelectGrouping ISelect.GroupBy(Expression> exp) { + if (exp == null) return this.InternalGroupBy(exp?.Body); for (var a = 0; a < exp.Parameters.Count; a++) _tables[a].Parameter = exp.Parameters[a]; - return this.InternalGroupBy(exp?.Body); + return this.InternalGroupBy(exp?.Body); } TMember ISelect.Max(Expression> column) { diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select6Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select6Provider.cs index ef946bc4..497ee66f 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select6Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select6Provider.cs @@ -36,10 +36,10 @@ namespace FreeSql.Internal.CommonProvider { return this.InternalAvgAsync(column?.Body); } - ISelectGrouping ISelect.GroupBy(Expression> exp) { - if (exp == null) return this.InternalGroupBy(exp?.Body); + ISelectGrouping ISelect.GroupBy(Expression> exp) { + if (exp == null) return this.InternalGroupBy(exp?.Body); for (var a = 0; a < exp.Parameters.Count; a++) _tables[a].Parameter = exp.Parameters[a]; - return this.InternalGroupBy(exp?.Body); + return this.InternalGroupBy(exp?.Body); } TMember ISelect.Max(Expression> column) { diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select7Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select7Provider.cs index 9a054d15..75c70ea4 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select7Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select7Provider.cs @@ -38,10 +38,10 @@ namespace FreeSql.Internal.CommonProvider { return this.InternalAvgAsync(column?.Body); } - ISelectGrouping ISelect.GroupBy(Expression> exp) { - if (exp == null) return this.InternalGroupBy(exp?.Body); + ISelectGrouping ISelect.GroupBy(Expression> exp) { + if (exp == null) return this.InternalGroupBy(exp?.Body); for (var a = 0; a < exp.Parameters.Count; a++) _tables[a].Parameter = exp.Parameters[a]; - return this.InternalGroupBy(exp?.Body); + return this.InternalGroupBy(exp?.Body); } TMember ISelect.Max(Expression> column) { diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select8Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select8Provider.cs index 5c0141ec..1abc8e53 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select8Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select8Provider.cs @@ -40,10 +40,10 @@ namespace FreeSql.Internal.CommonProvider { return this.InternalAvgAsync(column?.Body); } - ISelectGrouping ISelect.GroupBy(Expression> exp) { - if (exp == null) return this.InternalGroupBy(exp?.Body); + ISelectGrouping ISelect.GroupBy(Expression> exp) { + if (exp == null) return this.InternalGroupBy(exp?.Body); for (var a = 0; a < exp.Parameters.Count; a++) _tables[a].Parameter = exp.Parameters[a]; - return this.InternalGroupBy(exp?.Body); + return this.InternalGroupBy(exp?.Body); } TMember ISelect.Max(Expression> column) { diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select9Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select9Provider.cs index 3a933cf7..64b8e466 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select9Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select9Provider.cs @@ -42,10 +42,10 @@ namespace FreeSql.Internal.CommonProvider { return this.InternalAvgAsync(column?.Body); } - ISelectGrouping ISelect.GroupBy(Expression> exp) { - if (exp == null) return this.InternalGroupBy(exp?.Body); + ISelectGrouping ISelect.GroupBy(Expression> exp) { + if (exp == null) return this.InternalGroupBy(exp?.Body); for (var a = 0; a < exp.Parameters.Count; a++) _tables[a].Parameter = exp.Parameters[a]; - return this.InternalGroupBy(exp?.Body); + return this.InternalGroupBy(exp?.Body); } TMember ISelect.Max(Expression> column) { diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs index 2e07e6f3..4b9edbed 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs @@ -8,48 +8,89 @@ using System.Text; using System.Threading.Tasks; namespace FreeSql.Internal.CommonProvider { - class SelectGroupingProvider : ISelectGrouping { + class SelectGroupingProvider : ISelectGrouping { internal object _select; internal ReadAnonymousTypeInfo _map; internal CommonExpression _comonExp; - public SelectGroupingProvider(object select, ReadAnonymousTypeInfo map, CommonExpression comonExp) { + internal List _tables; + public SelectGroupingProvider(object select, ReadAnonymousTypeInfo map, CommonExpression comonExp, List tables) { _select = select; _map = map; _comonExp = comonExp; + _tables = tables; } 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; + if (members.Any() == false) return _map.DbField; + var parentName = ((members.FirstOrDefault() as MemberExpression)?.Expression as MemberExpression)?.Member.Name; + switch(parentName) { + case "Key": + 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; + case "Value": + var tb = _tables.First(); + var foridx = 0; + if (members.Length > 1) { + var mem0 = (members.FirstOrDefault() as MemberExpression); + var mem0Name = mem0?.Member.Name; + if (mem0Name?.StartsWith("Item") == true && int.TryParse(mem0Name.Substring(4), out var tryitemidx)) { + if (tryitemidx == 1) foridx++; + else { + var alias = $"SP10{(char)(96 + tryitemidx)}"; + var tmptb = _tables.Where(a => a.AliasInit == alias && a.Table.Type == mem0.Type).FirstOrDefault(); + if (tmptb != null) { + tb = tmptb; + foridx++; + } + } + } + } + var parmExp = Expression.Parameter(tb.Table.Type, tb.Alias); + Expression retExp = parmExp; + for (var a = foridx; a < members.Length; a++) { + switch(members[a].NodeType) { + case ExpressionType.Call: + retExp = Expression.Call(retExp, (members[a] as MethodCallExpression).Method); + break; + case ExpressionType.MemberAccess: + retExp = Expression.MakeMemberAccess(retExp, (members[a] as MemberExpression).Member); + break; + default: + return null; + } + } + return _comonExp.ExpressionLambdaToSql(retExp, _tables, null, null, SelectTableInfoType.From, true, true, CommonExpression.ExpressionStyle.Where); } - return read.DbField; + return null; } - public ISelectGrouping Having(Expression, bool>> exp) { + public ISelectGrouping Having(Expression, 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; } - public ISelectGrouping OrderBy(Expression, TMember>> column) { + public ISelectGrouping OrderBy(Expression, 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 OrderByDescending(Expression, TMember>> column) { + public ISelectGrouping OrderByDescending(Expression, 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 ToList(Expression, TReturn>> select) { + public List ToList(Expression, TReturn>> select) { var map = new ReadAnonymousTypeInfo(); var field = new StringBuilder(); var index = 0; @@ -59,7 +100,7 @@ namespace FreeSql.Internal.CommonProvider { method = method.MakeGenericMethod(typeof(TReturn)); return method.Invoke(_select, new object[] { (map, field.Length > 0 ? field.Remove(0, 2).ToString() : null) }) as List; } - public Task> ToListAsync(Expression, TReturn>> select) { + public Task> ToListAsync(Expression, TReturn>> select) { var map = new ReadAnonymousTypeInfo(); var field = new StringBuilder(); var index = 0; @@ -70,7 +111,7 @@ namespace FreeSql.Internal.CommonProvider { return method.Invoke(_select, new object[] { (map, field.Length > 0 ? field.Remove(0, 2).ToString() : null) }) as Task>; } - public string ToSql(Expression, TReturn>> select) { + public string ToSql(Expression, TReturn>> select) { var map = new ReadAnonymousTypeInfo(); var field = new StringBuilder(); var index = 0; @@ -80,21 +121,21 @@ namespace FreeSql.Internal.CommonProvider { return method.Invoke(_select, new object[] { field.Length > 0 ? field.Remove(0, 2).ToString() : null }) as string; } - public ISelectGrouping Skip(int offset) { + public ISelectGrouping Skip(int offset) { var method = _select.GetType().GetMethod("Skip", new[] { typeof(int) }); method.Invoke(_select, new object[] { offset }); return this; } - public ISelectGrouping Offset(int offset) => this.Skip(offset); + public ISelectGrouping Offset(int offset) => this.Skip(offset); - public ISelectGrouping Limit(int limit) { + public ISelectGrouping Limit(int limit) { var method = _select.GetType().GetMethod("Limit", new[] { typeof(int) }); method.Invoke(_select, new object[] { limit }); return this; } - public ISelectGrouping Take(int limit) => this.Limit(limit); + public ISelectGrouping Take(int limit) => this.Limit(limit); - public ISelectGrouping Page(int pageIndex, int pageSize) { + public ISelectGrouping Page(int pageIndex, int pageSize) { var method = _select.GetType().GetMethod("Page", new[] { typeof(int), typeof(int) }); method.Invoke(_select, new object[] { pageIndex, pageSize }); return this; diff --git a/FreeSql/Internal/CommonUtils.cs b/FreeSql/Internal/CommonUtils.cs index fa35f967..f62d1772 100644 --- a/FreeSql/Internal/CommonUtils.cs +++ b/FreeSql/Internal/CommonUtils.cs @@ -21,7 +21,7 @@ namespace FreeSql.Internal { internal abstract string QuoteSqlName(string name); internal abstract string QuoteParamterName(string name); internal abstract string IsNull(string sql, object value); - internal abstract string StringConcat(string left, string right, Type leftType, Type rightType); + internal abstract string StringConcat(string[] objs, Type[] types); internal abstract string Mod(string left, string right, Type leftType, Type rightType); internal abstract string QuoteWriteParamter(Type type, string paramterName); internal abstract string QuoteReadColumn(Type type, string columnName); diff --git a/FreeSql/Internal/Model/SelectTableInfo.cs b/FreeSql/Internal/Model/SelectTableInfo.cs index 0aa138f2..9e880f9d 100644 --- a/FreeSql/Internal/Model/SelectTableInfo.cs +++ b/FreeSql/Internal/Model/SelectTableInfo.cs @@ -3,7 +3,16 @@ namespace FreeSql.Internal.Model { class SelectTableInfo { public TableInfo Table { get; set; } - public string Alias { get; set; } + + private string _alias; + public string Alias { + get => _alias; + set { + _alias = value; + if (string.IsNullOrEmpty(AliasInit)) AliasInit = value; + } + } + public string AliasInit { get; set; } public string On { get; set; } public string NavigateCondition { get; set; } public ParameterExpression Parameter { get; set; } diff --git a/FreeSql/MySql/MySqlExpression.cs b/FreeSql/MySql/MySqlExpression.cs index 3c5bf4d2..129b900c 100644 --- a/FreeSql/MySql/MySqlExpression.cs +++ b/FreeSql/MySql/MySqlExpression.cs @@ -208,6 +208,8 @@ namespace FreeSql.MySql { case "IsNullOrEmpty": var arg1 = getExp(exp.Arguments[0]); return $"({arg1} is null or {arg1} = '')"; + case "Concat": + return _common.StringConcat(exp.Arguments.Select(a => getExp(a)).ToArray(), null); } } else { var left = getExp(exp.Object); @@ -335,7 +337,7 @@ namespace FreeSql.MySql { } break; case "Equals": return $"({left} = {getExp(exp.Arguments[0])})"; - case "CompareTo": return $"timestampdiff(microsecond,{getExp(exp.Arguments[0])},{left})"; + case "CompareTo": return $"timestampdiff(microsecond,{args1},{left})"; case "ToString": return $"date_format({left}, '%Y-%m-%d %H:%i:%s.%f')"; } } diff --git a/FreeSql/MySql/MySqlUtils.cs b/FreeSql/MySql/MySqlUtils.cs index 6e926867..028389e2 100644 --- a/FreeSql/MySql/MySqlUtils.cs +++ b/FreeSql/MySql/MySqlUtils.cs @@ -4,6 +4,7 @@ using MySql.Data.MySqlClient; using System; using System.Collections.Generic; using System.Data.Common; +using System.Linq; using System.Text; namespace FreeSql.MySql { @@ -50,7 +51,7 @@ namespace FreeSql.MySql { } internal override string QuoteParamterName(string name) => $"?{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}"; internal override string IsNull(string sql, object value) => $"ifnull({sql}, {value})"; - internal override string StringConcat(string left, string right, Type leftType, Type rightType) => $"concat({left}, {right})"; + internal override string StringConcat(string[] objs, Type[] types) => $"concat({string.Join(", ", objs)})"; internal override string Mod(string left, string right, Type leftType, Type rightType) => $"{left} % {right}"; internal override string QuoteWriteParamter(Type type, string paramterName) { switch (type.FullName) { diff --git a/FreeSql/Oracle/OracleExpression.cs b/FreeSql/Oracle/OracleExpression.cs index 7c1198c8..f9a54dfd 100644 --- a/FreeSql/Oracle/OracleExpression.cs +++ b/FreeSql/Oracle/OracleExpression.cs @@ -208,6 +208,8 @@ namespace FreeSql.Oracle { case "IsNullOrEmpty": var arg1 = getExp(exp.Arguments[0]); return $"({arg1} is null or {arg1} = '')"; + case "Concat": + return _common.StringConcat(exp.Arguments.Select(a => getExp(a)).ToArray(), null); } } else { var left = getExp(exp.Object); diff --git a/FreeSql/Oracle/OracleUtils.cs b/FreeSql/Oracle/OracleUtils.cs index e1ea4f42..752b29b1 100644 --- a/FreeSql/Oracle/OracleUtils.cs +++ b/FreeSql/Oracle/OracleUtils.cs @@ -46,7 +46,7 @@ namespace FreeSql.Oracle { } internal override string QuoteParamterName(string name) => $":{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}"; internal override string IsNull(string sql, object value) => $"nvl({sql}, {value})"; - internal override string StringConcat(string left, string right, Type leftType, Type rightType) => $"{left} || {right}"; + internal override string StringConcat(string[] objs, Type[] types) => $"{string.Join(" || ", objs)}"; internal override string Mod(string left, string right, Type leftType, Type rightType) => $"mod({left}, {right})"; internal override string QuoteWriteParamter(Type type, string paramterName) => paramterName; diff --git a/FreeSql/PostgreSQL/PostgreSQLExpression.cs b/FreeSql/PostgreSQL/PostgreSQLExpression.cs index 7605f31c..e9c169d8 100644 --- a/FreeSql/PostgreSQL/PostgreSQLExpression.cs +++ b/FreeSql/PostgreSQL/PostgreSQLExpression.cs @@ -303,6 +303,8 @@ namespace FreeSql.PostgreSQL { case "IsNullOrEmpty": var arg1 = getExp(exp.Arguments[0]); return $"({arg1} is null or {arg1} = '')"; + case "Concat": + return _common.StringConcat(exp.Arguments.Select(a => getExp(a)).ToArray(), null); } } else { var left = getExp(exp.Object); diff --git a/FreeSql/PostgreSQL/PostgreSQLUtils.cs b/FreeSql/PostgreSQL/PostgreSQLUtils.cs index b74915a2..e76b25e4 100644 --- a/FreeSql/PostgreSQL/PostgreSQLUtils.cs +++ b/FreeSql/PostgreSQL/PostgreSQLUtils.cs @@ -105,7 +105,7 @@ namespace FreeSql.PostgreSQL { } internal override string QuoteParamterName(string name) => $"@{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}"; internal override string IsNull(string sql, object value) => $"coalesce({sql}, {value})"; - internal override string StringConcat(string left, string right, Type leftType, Type rightType) => $"{left} || {right}"; + internal override string StringConcat(string[] objs, Type[] types) => $"{string.Join(" || ", objs)}"; internal override string Mod(string left, string right, Type leftType, Type rightType) => $"{left} % {right}"; internal override string QuoteWriteParamter(Type type, string paramterName) => paramterName; diff --git a/FreeSql/SqlServer/SqlServerExpression.cs b/FreeSql/SqlServer/SqlServerExpression.cs index 81e1bc86..bfcad652 100644 --- a/FreeSql/SqlServer/SqlServerExpression.cs +++ b/FreeSql/SqlServer/SqlServerExpression.cs @@ -211,6 +211,8 @@ namespace FreeSql.SqlServer { case "IsNullOrEmpty": var arg1 = getExp(exp.Arguments[0]); return $"({arg1} is null or {arg1} = '')"; + case "Concat": + return _common.StringConcat(exp.Arguments.Select(a => getExp(a)).ToArray(), exp.Arguments.Select(a => a.Type).ToArray()); } } else { var left = getExp(exp.Object); diff --git a/FreeSql/SqlServer/SqlServerUtils.cs b/FreeSql/SqlServer/SqlServerUtils.cs index 6c65db4a..c84e2071 100644 --- a/FreeSql/SqlServer/SqlServerUtils.cs +++ b/FreeSql/SqlServer/SqlServerUtils.cs @@ -43,7 +43,13 @@ namespace FreeSql.SqlServer { } internal override string QuoteParamterName(string name) => $"@{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}"; internal override string IsNull(string sql, object value) => $"isnull({sql}, {value})"; - internal override string StringConcat(string left, string right, Type leftType, Type rightType) => $"{(leftType.FullName == "System.String" ? left : $"cast({left} as nvarchar)")} + {(rightType.FullName == "System.String" ? right : $"cast({right} as nvarchar)")}"; + internal override string StringConcat(string[] objs, Type[] types) { + var sb = new StringBuilder(); + var news = new string[objs.Length]; + for (var a = 0; a < objs.Length; a++) + news[a] = types[a] == typeof(string) ? objs[a] : $"cast({objs[a]} as nvarchar)"; + return string.Join(" + ", news); + } internal override string Mod(string left, string right, Type leftType, Type rightType) => $"{left} % {right}"; internal override string QuoteWriteParamter(Type type, string paramterName) => paramterName; diff --git a/FreeSql/Sqlite/SqliteExpression.cs b/FreeSql/Sqlite/SqliteExpression.cs index 6c31d25d..47e005bf 100644 --- a/FreeSql/Sqlite/SqliteExpression.cs +++ b/FreeSql/Sqlite/SqliteExpression.cs @@ -208,6 +208,8 @@ namespace FreeSql.Sqlite { case "IsNullOrEmpty": var arg1 = getExp(exp.Arguments[0]); return $"({arg1} is null or {arg1} = '')"; + case "Concat": + return _common.StringConcat(exp.Arguments.Select(a => getExp(a)).ToArray(), null); } } else { var left = getExp(exp.Object); diff --git a/FreeSql/Sqlite/SqliteUtils.cs b/FreeSql/Sqlite/SqliteUtils.cs index 3a8bea39..98540fe1 100644 --- a/FreeSql/Sqlite/SqliteUtils.cs +++ b/FreeSql/Sqlite/SqliteUtils.cs @@ -61,7 +61,7 @@ namespace FreeSql.Sqlite { } internal override string QuoteParamterName(string name) => $"@{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}"; internal override string IsNull(string sql, object value) => $"ifnull({sql}, {value})"; - internal override string StringConcat(string left, string right, Type leftType, Type rightType) => $"{left} || {right}"; + internal override string StringConcat(string[] objs, Type[] types) => $"{string.Join(" || ", objs)}"; internal override string Mod(string left, string right, Type leftType, Type rightType) => $"{left} % {right}"; internal override string QuoteWriteParamter(Type type, string paramterName) => paramterName;