From 4cde2a328087879fa67be68fc703ad7102e06bec Mon Sep 17 00:00:00 2001
From: 28810 <28810@YEXIANGQIN>
Date: Sat, 27 Jun 2020 04:21:00 +0800
Subject: [PATCH] =?UTF-8?q?-=20=E5=A2=9E=E5=8A=A0=20ISelect.AsCteTree()=20?=
=?UTF-8?q?=E9=80=92=E5=BD=92=E6=9F=A5=E8=AF=A2=E6=A0=91=E8=A1=A8=E6=89=80?=
=?UTF-8?q?=E6=9C=89=E5=AD=90=E8=AE=B0=E5=BD=95=EF=BC=9B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
FreeSql.DbContext/FreeSql.DbContext.xml | 16 ----
.../MySqlConnector/Curd/MySqlSelectTest.cs | 24 +++++-
.../Dameng/Curd/DamengSelectTest.cs | 24 +++++-
.../KingbaseES/Curd/KingbaseESSelectTest.cs | 24 +++++-
.../MySql/Curd/MySqlSelectTest.cs | 24 +++++-
.../Oracle/Curd/OracleSelectTest.cs | 24 +++++-
.../PostgreSQL/Curd/PostgreSQLSelectTest.cs | 24 +++++-
.../SqlServer/Curd/SqlServerSelectTest.cs | 24 +++++-
.../Dameng/Curd/DamengSelectTest.cs | 24 +++++-
.../MySql/Curd/MySqlSelectTest.cs | 24 +++++-
.../Oracle/Curd/OracleSelectTest.cs | 24 +++++-
.../PostgreSQL/Curd/PostgreSQLSelectTest.cs | 24 +++++-
.../SqlServer/Curd/SqlServerSelectTest.cs | 24 +++++-
.../Sqlite/Curd/SqliteSelectTest.cs | 24 +++++-
FreeSql/Extensions/FreeSqlGlobalExtensions.cs | 76 +++++++++++++++++++
FreeSql/FreeSql.xml | 10 +++
.../CommonProvider/AdoProvider/AdoProvider.cs | 2 +-
.../AdoProvider/AdoProviderAsync.cs | 2 +-
.../AdoProvider/AdoProviderUtils.cs | 6 ++
.../SelectProvider/Select0Provider.cs | 4 +-
20 files changed, 395 insertions(+), 33 deletions(-)
diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml
index 4854f49c..132d875e 100644
--- a/FreeSql.DbContext/FreeSql.DbContext.xml
+++ b/FreeSql.DbContext/FreeSql.DbContext.xml
@@ -125,13 +125,6 @@
清空状态数据
-
-
- 根据 lambda 条件删除数据
-
-
-
-
添加
@@ -486,14 +479,5 @@
-
-
- 批量注入 Repository,可以参考代码自行调整
-
-
-
-
-
-
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 554be95f..956d0aaf 100644
--- a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs
@@ -1865,7 +1865,7 @@ WHERE ((b.`IsFinished` OR a.`TaskType` = 3) AND b.`EnabledMark` = 1)", groupsql1
new VM_District_Child
{
Code = "110000",
- Name = "北京市",
+ Name = "北京",
Childs = new List(new[] {
new VM_District_Child{ Code="110100", Name = "北京市" },
new VM_District_Child{ Code="110101", Name = "东城区" },
@@ -1903,6 +1903,28 @@ WHERE ((b.`IsFinished` OR a.`TaskType` = 3) AND b.`EnabledMark` = 1)", groupsql1
Assert.Equal(2, t3[0].Childs[0].Childs.Count);
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ //t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToTreeList();
+ //Assert.Single(t3);
+ //Assert.Equal("100000", t3[0].Code);
+ //Assert.Single(t3[0].Childs);
+ //Assert.Equal("110000", t3[0].Childs[0].Code);
+ //Assert.Equal(2, t3[0].Childs[0].Childs.Count);
+ //Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
+ //Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ //t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToList();
+ //Assert.Equal(4, t3.Count);
+ //Assert.Equal("100000", t3[0].Code);
+ //Assert.Equal("110000", t3[1].Code);
+ //Assert.Equal("110100", t3[2].Code);
+ //Assert.Equal("110101", t3[3].Code);
+
+ //t3 = fsql.Select().Where(a => a.Name == "北京").AsCteTree().OrderBy(a => a.Code).ToList();
+ //Assert.Equal(3, t3.Count);
+ //Assert.Equal("110000", t3[0].Code);
+ //Assert.Equal("110100", t3[1].Code);
+ //Assert.Equal("110101", t3[2].Code);
}
[Table(Name = "D_District")]
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 20705c2a..6eeafa37 100644
--- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs
@@ -1715,7 +1715,7 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE""
new VM_District_Child
{
Code = "110000",
- Name = "北京市",
+ Name = "北京",
Childs = new List(new[] {
new VM_District_Child{ Code="110100", Name = "北京市" },
new VM_District_Child{ Code="110101", Name = "东城区" },
@@ -1753,6 +1753,28 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE""
Assert.Equal(2, t3[0].Childs[0].Childs.Count);
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToTreeList();
+ Assert.Single(t3);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Single(t3[0].Childs);
+ Assert.Equal("110000", t3[0].Childs[0].Code);
+ Assert.Equal(2, t3[0].Childs[0].Childs.Count);
+ Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
+ Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(4, t3.Count);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Equal("110000", t3[1].Code);
+ Assert.Equal("110100", t3[2].Code);
+ Assert.Equal("110101", t3[3].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "北京").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(3, t3.Count);
+ Assert.Equal("110000", t3[0].Code);
+ Assert.Equal("110100", t3[1].Code);
+ Assert.Equal("110101", t3[2].Code);
}
[Table(Name = "D_District")]
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 fed8ea69..0e0d8697 100644
--- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/KingbaseES/Curd/KingbaseESSelectTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/KingbaseES/Curd/KingbaseESSelectTest.cs
@@ -1680,7 +1680,7 @@ WHERE ((((a.""ID"")::varchar) in (SELECT b.""TITLE""
new VM_District_Child
{
Code = "110000",
- Name = "北京市",
+ Name = "北京",
Childs = new List(new[] {
new VM_District_Child{ Code="110100", Name = "北京市" },
new VM_District_Child{ Code="110101", Name = "东城区" },
@@ -1718,6 +1718,28 @@ WHERE ((((a.""ID"")::varchar) in (SELECT b.""TITLE""
Assert.Equal(2, t3[0].Childs[0].Childs.Count);
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToTreeList();
+ Assert.Single(t3);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Single(t3[0].Childs);
+ Assert.Equal("110000", t3[0].Childs[0].Code);
+ Assert.Equal(2, t3[0].Childs[0].Childs.Count);
+ Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
+ Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(4, t3.Count);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Equal("110000", t3[1].Code);
+ Assert.Equal("110100", t3[2].Code);
+ Assert.Equal("110101", t3[3].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "北京").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(3, t3.Count);
+ Assert.Equal("110000", t3[0].Code);
+ Assert.Equal("110100", t3[1].Code);
+ Assert.Equal("110101", t3[2].Code);
}
[Table(Name = "D_District")]
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 fc1cd64f..546a0e06 100644
--- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs
@@ -1876,7 +1876,7 @@ WHERE ((b.`IsFinished` OR a.`TaskType` = 3) AND b.`EnabledMark` = 1)", groupsql1
new VM_District_Child
{
Code = "110000",
- Name = "北京市",
+ Name = "北京",
Childs = new List(new[] {
new VM_District_Child{ Code="110100", Name = "北京市" },
new VM_District_Child{ Code="110101", Name = "东城区" },
@@ -1914,6 +1914,28 @@ WHERE ((b.`IsFinished` OR a.`TaskType` = 3) AND b.`EnabledMark` = 1)", groupsql1
Assert.Equal(2, t3[0].Childs[0].Childs.Count);
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ //t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToTreeList();
+ //Assert.Single(t3);
+ //Assert.Equal("100000", t3[0].Code);
+ //Assert.Single(t3[0].Childs);
+ //Assert.Equal("110000", t3[0].Childs[0].Code);
+ //Assert.Equal(2, t3[0].Childs[0].Childs.Count);
+ //Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
+ //Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ //t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToList();
+ //Assert.Equal(4, t3.Count);
+ //Assert.Equal("100000", t3[0].Code);
+ //Assert.Equal("110000", t3[1].Code);
+ //Assert.Equal("110100", t3[2].Code);
+ //Assert.Equal("110101", t3[3].Code);
+
+ //t3 = fsql.Select().Where(a => a.Name == "北京").AsCteTree().OrderBy(a => a.Code).ToList();
+ //Assert.Equal(3, t3.Count);
+ //Assert.Equal("110000", t3[0].Code);
+ //Assert.Equal("110100", t3[1].Code);
+ //Assert.Equal("110101", t3[2].Code);
}
[Table(Name = "D_District")]
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 fa4e36d9..8b849b1a 100644
--- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs
@@ -1716,7 +1716,7 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE""
new VM_District_Child
{
Code = "110000",
- Name = "北京市",
+ Name = "北京",
Childs = new List(new[] {
new VM_District_Child{ Code="110100", Name = "北京市" },
new VM_District_Child{ Code="110101", Name = "东城区" },
@@ -1754,6 +1754,28 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE""
Assert.Equal(2, t3[0].Childs[0].Childs.Count);
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToTreeList();
+ Assert.Single(t3);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Single(t3[0].Childs);
+ Assert.Equal("110000", t3[0].Childs[0].Code);
+ Assert.Equal(2, t3[0].Childs[0].Childs.Count);
+ Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
+ Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(4, t3.Count);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Equal("110000", t3[1].Code);
+ Assert.Equal("110100", t3[2].Code);
+ Assert.Equal("110101", t3[3].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "北京").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(3, t3.Count);
+ Assert.Equal("110000", t3[0].Code);
+ Assert.Equal("110100", t3[1].Code);
+ Assert.Equal("110101", t3[2].Code);
}
[Table(Name = "D_District")]
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 f0e048a1..96cec0f8 100644
--- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs
@@ -1775,7 +1775,7 @@ WHERE ((((a.""id"")::varchar) in (SELECT b.""title""
new VM_District_Child
{
Code = "110000",
- Name = "北京市",
+ Name = "北京",
Childs = new List(new[] {
new VM_District_Child{ Code="110100", Name = "北京市" },
new VM_District_Child{ Code="110101", Name = "东城区" },
@@ -1813,6 +1813,28 @@ WHERE ((((a.""id"")::varchar) in (SELECT b.""title""
Assert.Equal(2, t3[0].Childs[0].Childs.Count);
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToTreeList();
+ Assert.Single(t3);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Single(t3[0].Childs);
+ Assert.Equal("110000", t3[0].Childs[0].Code);
+ Assert.Equal(2, t3[0].Childs[0].Childs.Count);
+ Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
+ Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(4, t3.Count);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Equal("110000", t3[1].Code);
+ Assert.Equal("110100", t3[2].Code);
+ Assert.Equal("110101", t3[3].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "北京").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(3, t3.Count);
+ Assert.Equal("110000", t3[0].Code);
+ Assert.Equal("110100", t3[1].Code);
+ Assert.Equal("110101", t3[2].Code);
}
[Table(Name = "D_District")]
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 ffd98967..92b4fe3f 100644
--- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs
@@ -1666,7 +1666,7 @@ WHERE (((cast(a.[Id] as nvarchar(100))) in (SELECT b.[Title]
new VM_District_Child
{
Code = "110000",
- Name = "北京市",
+ Name = "北京",
Childs = new List(new[] {
new VM_District_Child{ Code="110100", Name = "北京市" },
new VM_District_Child{ Code="110101", Name = "东城区" },
@@ -1704,6 +1704,28 @@ WHERE (((cast(a.[Id] as nvarchar(100))) in (SELECT b.[Title]
Assert.Equal(2, t3[0].Childs[0].Childs.Count);
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToTreeList();
+ Assert.Single(t3);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Single(t3[0].Childs);
+ Assert.Equal("110000", t3[0].Childs[0].Code);
+ Assert.Equal(2, t3[0].Childs[0].Childs.Count);
+ Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
+ Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(4, t3.Count);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Equal("110000", t3[1].Code);
+ Assert.Equal("110100", t3[2].Code);
+ Assert.Equal("110101", t3[3].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "北京").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(3, t3.Count);
+ Assert.Equal("110000", t3[0].Code);
+ Assert.Equal("110100", t3[1].Code);
+ Assert.Equal("110101", t3[2].Code);
}
[Table(Name = "D_District")]
diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs
index c19346f9..c6e2751f 100644
--- a/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs
@@ -1716,7 +1716,7 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE""
new VM_District_Child
{
Code = "110000",
- Name = "北京市",
+ Name = "北京",
Childs = new List(new[] {
new VM_District_Child{ Code="110100", Name = "北京市" },
new VM_District_Child{ Code="110101", Name = "东城区" },
@@ -1754,6 +1754,28 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE""
Assert.Equal(2, t3[0].Childs[0].Childs.Count);
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToTreeList();
+ Assert.Single(t3);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Single(t3[0].Childs);
+ Assert.Equal("110000", t3[0].Childs[0].Code);
+ Assert.Equal(2, t3[0].Childs[0].Childs.Count);
+ Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
+ Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(4, t3.Count);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Equal("110000", t3[1].Code);
+ Assert.Equal("110100", t3[2].Code);
+ Assert.Equal("110101", t3[3].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "北京").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(3, t3.Count);
+ Assert.Equal("110000", t3[0].Code);
+ Assert.Equal("110100", t3[1].Code);
+ Assert.Equal("110101", t3[2].Code);
}
[Table(Name = "D_District")]
diff --git a/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs
index bfe8db80..d4166792 100644
--- a/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs
@@ -1929,7 +1929,7 @@ WHERE ((b.`IsFinished` OR a.`TaskType` = 3) AND b.`EnabledMark` = 1)", groupsql1
new VM_District_Child
{
Code = "110000",
- Name = "北京市",
+ Name = "北京",
Childs = new List(new[] {
new VM_District_Child{ Code="110100", Name = "北京市" },
new VM_District_Child{ Code="110101", Name = "东城区" },
@@ -1967,6 +1967,28 @@ WHERE ((b.`IsFinished` OR a.`TaskType` = 3) AND b.`EnabledMark` = 1)", groupsql1
Assert.Equal(2, t3[0].Childs[0].Childs.Count);
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ //t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToTreeList();
+ //Assert.Single(t3);
+ //Assert.Equal("100000", t3[0].Code);
+ //Assert.Single(t3[0].Childs);
+ //Assert.Equal("110000", t3[0].Childs[0].Code);
+ //Assert.Equal(2, t3[0].Childs[0].Childs.Count);
+ //Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
+ //Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ //t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToList();
+ //Assert.Equal(4, t3.Count);
+ //Assert.Equal("100000", t3[0].Code);
+ //Assert.Equal("110000", t3[1].Code);
+ //Assert.Equal("110100", t3[2].Code);
+ //Assert.Equal("110101", t3[3].Code);
+
+ //t3 = fsql.Select().Where(a => a.Name == "北京").AsCteTree().OrderBy(a => a.Code).ToList();
+ //Assert.Equal(3, t3.Count);
+ //Assert.Equal("110000", t3[0].Code);
+ //Assert.Equal("110100", t3[1].Code);
+ //Assert.Equal("110101", t3[2].Code);
}
[Table(Name = "D_District")]
diff --git a/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs
index c61ce957..3a922613 100644
--- a/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs
@@ -1716,7 +1716,7 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE""
new VM_District_Child
{
Code = "110000",
- Name = "北京市",
+ Name = "北京",
Childs = new List(new[] {
new VM_District_Child{ Code="110100", Name = "北京市" },
new VM_District_Child{ Code="110101", Name = "东城区" },
@@ -1754,6 +1754,28 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE""
Assert.Equal(2, t3[0].Childs[0].Childs.Count);
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToTreeList();
+ Assert.Single(t3);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Single(t3[0].Childs);
+ Assert.Equal("110000", t3[0].Childs[0].Code);
+ Assert.Equal(2, t3[0].Childs[0].Childs.Count);
+ Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
+ Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(4, t3.Count);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Equal("110000", t3[1].Code);
+ Assert.Equal("110100", t3[2].Code);
+ Assert.Equal("110101", t3[3].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "北京").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(3, t3.Count);
+ Assert.Equal("110000", t3[0].Code);
+ Assert.Equal("110100", t3[1].Code);
+ Assert.Equal("110101", t3[2].Code);
}
[Table(Name = "D_District")]
diff --git a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs
index db9854e2..4ce6ea32 100644
--- a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs
@@ -1791,7 +1791,7 @@ WHERE ((((a.""id"")::varchar) in (SELECT b.""title""
new VM_District_Child
{
Code = "110000",
- Name = "北京市",
+ Name = "北京",
Childs = new List(new[] {
new VM_District_Child{ Code="110100", Name = "北京市" },
new VM_District_Child{ Code="110101", Name = "东城区" },
@@ -1829,6 +1829,28 @@ WHERE ((((a.""id"")::varchar) in (SELECT b.""title""
Assert.Equal(2, t3[0].Childs[0].Childs.Count);
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToTreeList();
+ Assert.Single(t3);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Single(t3[0].Childs);
+ Assert.Equal("110000", t3[0].Childs[0].Code);
+ Assert.Equal(2, t3[0].Childs[0].Childs.Count);
+ Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
+ Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(4, t3.Count);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Equal("110000", t3[1].Code);
+ Assert.Equal("110100", t3[2].Code);
+ Assert.Equal("110101", t3[3].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "北京").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(3, t3.Count);
+ Assert.Equal("110000", t3[0].Code);
+ Assert.Equal("110100", t3[1].Code);
+ Assert.Equal("110101", t3[2].Code);
}
[Table(Name = "D_District")]
diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs
index dd8daa73..3efaedbf 100644
--- a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs
@@ -1747,7 +1747,7 @@ WHERE (((cast(a.[Id] as nvarchar(100))) in (SELECT b.[Title]
new VM_District_Child
{
Code = "110000",
- Name = "北京市",
+ Name = "北京",
Childs = new List(new[] {
new VM_District_Child{ Code="110100", Name = "北京市" },
new VM_District_Child{ Code="110101", Name = "东城区" },
@@ -1785,6 +1785,28 @@ WHERE (((cast(a.[Id] as nvarchar(100))) in (SELECT b.[Title]
Assert.Equal(2, t3[0].Childs[0].Childs.Count);
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToTreeList();
+ Assert.Single(t3);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Single(t3[0].Childs);
+ Assert.Equal("110000", t3[0].Childs[0].Code);
+ Assert.Equal(2, t3[0].Childs[0].Childs.Count);
+ Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
+ Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(4, t3.Count);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Equal("110000", t3[1].Code);
+ Assert.Equal("110100", t3[2].Code);
+ Assert.Equal("110101", t3[3].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "北京").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(3, t3.Count);
+ Assert.Equal("110000", t3[0].Code);
+ Assert.Equal("110100", t3[1].Code);
+ Assert.Equal("110101", t3[2].Code);
}
[Table(Name = "D_District")]
diff --git a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs
index f117bdd9..9631464f 100644
--- a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs
@@ -1865,7 +1865,7 @@ WHERE (((cast(a.""Id"" as character)) in (SELECT b.""Title""
new VM_District_Child
{
Code = "110000",
- Name = "北京市",
+ Name = "北京",
Childs = new List(new[] {
new VM_District_Child{ Code="110100", Name = "北京市" },
new VM_District_Child{ Code="110101", Name = "东城区" },
@@ -1903,6 +1903,28 @@ WHERE (((cast(a.""Id"" as character)) in (SELECT b.""Title""
Assert.Equal(2, t3[0].Childs[0].Childs.Count);
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToTreeList();
+ Assert.Single(t3);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Single(t3[0].Childs);
+ Assert.Equal("110000", t3[0].Childs[0].Code);
+ Assert.Equal(2, t3[0].Childs[0].Childs.Count);
+ Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
+ Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "中国").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(4, t3.Count);
+ Assert.Equal("100000", t3[0].Code);
+ Assert.Equal("110000", t3[1].Code);
+ Assert.Equal("110100", t3[2].Code);
+ Assert.Equal("110101", t3[3].Code);
+
+ t3 = fsql.Select().Where(a => a.Name == "北京").AsCteTree().OrderBy(a => a.Code).ToList();
+ Assert.Equal(3, t3.Count);
+ Assert.Equal("110000", t3[0].Code);
+ Assert.Equal("110100", t3[1].Code);
+ Assert.Equal("110101", t3[2].Code);
}
[Table(Name = "D_District")]
diff --git a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs
index ab1b955e..9b16690d 100644
--- a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs
+++ b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs
@@ -385,4 +385,80 @@ public static partial class FreeSqlGlobalExtensions
}
#endif
#endregion
+
+ #region WhereTree(..) 递归查询
+ ///
+ /// 使用递归 CTE 查询树型的所有子数据。
+ /// 通过测试的数据库:MySql8.0、SqlServer、PostgreSQL、Oracle、Sqlite、达梦、人大金仓
+ ///
+ ///
+ ///
+ /// 深度
+ ///
+ public static ISelect AsCteTree(this ISelect that, int depth = -1) where T1 : class
+ {
+ var select = that as Select1Provider;
+ var tb = select._tables[0].Table;
+ var navs = tb.Properties.Select(a => tb.GetTableRef(a.Key, false))
+ .Where(a => a != null &&
+ a.RefType == FreeSql.Internal.Model.TableRefType.OneToMany &&
+ a.RefEntityType == tb.Type).ToArray();
+
+ if (navs.Length != 1) throw new ArgumentException($"{tb.Type.FullName} 不是父子关系,无法使用该功能");
+ var tbref = navs[0];
+
+ var cteName = "as_cte_tree";
+ if (select._orm.CodeFirst.IsSyncStructureToLower) cteName = cteName.ToLower();
+ if (select._orm.CodeFirst.IsSyncStructureToUpper) cteName = cteName.ToUpper();
+ var sql1 = select.ToSql($"0 as as_cte_tree_depth, {select.GetAllFieldExpressionTreeLevel2().Field}").Trim();
+
+ select._where.Clear();
+ select.As("wct2");
+ var sql2Field = select.GetAllFieldExpressionTreeLevel2().Field;
+ var sql2 = select
+ .AsAlias((type, old) => type == tb.Type ? old.Replace("wct2", "wct1") : old)
+ .AsTable((type, old) => type == tb.Type ? cteName : old)
+ .InnerJoin($"{select._commonUtils.QuoteSqlName(tb.DbName)} wct2 ON {string.Join(" and ", tbref.Columns.Select((a,z) => $"wct2.{select._commonUtils.QuoteSqlName(tbref.RefColumns[z].Attribute.Name)} = wct1.{select._commonUtils.QuoteSqlName(a.Attribute.Name)}"))}")
+ .ToSql($"wct1.as_cte_tree_depth + 1 as as_cte_tree_depth, {sql2Field}").Trim();
+
+ var newSelect = select._orm.Select()
+ .AsType(tb.Type)
+ .AsTable((type, old) => type == tb.Type ? cteName : old)
+ .WhereIf(depth > 0, $"a.as_cte_tree_depth < {depth + 1}") as Select1Provider;
+
+ var nsselsb = new StringBuilder();
+ if (AdoProvider.IsFromSlave(select._select) == false) nsselsb.Append(" "); //读写分离规则,如果强制读主库,则在前面加个空格
+ nsselsb.Append("WITH ");
+ switch (select._orm.Ado.DataType)
+ {
+ case DataType.PostgreSQL:
+ case DataType.OdbcPostgreSQL:
+ case DataType.OdbcKingbaseES:
+ case DataType.ShenTong: //神通测试未通过
+ case DataType.MySql:
+ case DataType.OdbcMySql:
+ nsselsb.Append("RECURSIVE ");
+ break;
+ }
+ nsselsb.Append(select._commonUtils.QuoteSqlName(cteName));
+ switch (select._orm.Ado.DataType)
+ {
+ case DataType.Oracle: //[Err] ORA-32039: recursive WITH clause must have column alias list
+ case DataType.OdbcOracle:
+ case DataType.Dameng: //递归 WITH 子句必须具有列别名列表
+ case DataType.OdbcDameng:
+ nsselsb.Append($"(as_cte_tree_depth, {sql2Field.Replace("wct2.", "")})");
+ break;
+ }
+ nsselsb.Append(@"
+as
+(
+").Append(sql1).Append("\r\n\r\nunion all\r\n\r\n").Append(sql2).Append(@"
+)
+SELECT ");
+ newSelect._select = nsselsb.ToString();
+ nsselsb.Clear();
+ return newSelect;
+ }
+ #endregion
}
\ No newline at end of file
diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml
index 5d1ff11c..8738cbb9 100644
--- a/FreeSql/FreeSql.xml
+++ b/FreeSql/FreeSql.xml
@@ -3653,6 +3653,16 @@
+
+
+ 使用递归 CTE 查询树型的所有子数据。
+ 通过测试的数据库:MySql8.0、SqlServer、PostgreSQL、Oracle、Sqlite、达梦、人大金仓
+
+
+
+ 深度
+
+
使用 and 拼接两个 lambda 表达式
diff --git a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs
index 1d31f146..bde0e6e8 100644
--- a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs
+++ b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs
@@ -533,7 +533,7 @@ namespace FreeSql.Internal.CommonProvider
if (transaction == null && connection == null)
{
//读写分离规则
- if (this.SlavePools.Any() && cmdText.StartsWith("SELECT ", StringComparison.CurrentCultureIgnoreCase))
+ if (this.SlavePools.Any() && IsFromSlave(cmdText))
{
var availables = slaveUnavailables == 0 ?
//查从库
diff --git a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs
index 356222af..f6784181 100644
--- a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs
+++ b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs
@@ -458,7 +458,7 @@ namespace FreeSql.Internal.CommonProvider
if (transaction == null && connection == null)
{
//读写分离规则
- if (this.SlavePools.Any() && cmdText.StartsWith("SELECT ", StringComparison.CurrentCultureIgnoreCase))
+ if (this.SlavePools.Any() && IsFromSlave(cmdText))
{
var availables = slaveUnavailables == 0 ?
//查从库
diff --git a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderUtils.cs b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderUtils.cs
index a8b1d542..a5461a4d 100644
--- a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderUtils.cs
+++ b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderUtils.cs
@@ -45,5 +45,11 @@ namespace FreeSql.Internal.CommonProvider
return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
}
+
+ public static bool IsFromSlave(string cmdText)
+ {
+ return cmdText.StartsWith("SELECT ", StringComparison.CurrentCultureIgnoreCase) ||
+ cmdText.StartsWith("WITH ", StringComparison.CurrentCultureIgnoreCase);
+ }
}
}
diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs
index 62b9784d..79fb1956 100644
--- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs
+++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs
@@ -596,7 +596,7 @@ namespace FreeSql.Internal.CommonProvider
public int FieldCount { get; set; }
public Func Read { get; set; }
}
- protected GetAllFieldExpressionTreeInfo GetAllFieldExpressionTreeLevelAll()
+ public GetAllFieldExpressionTreeInfo GetAllFieldExpressionTreeLevelAll()
{
return _dicGetAllFieldExpressionTree.GetOrAdd($"*{string.Join("+", _tables.Select(a => $"{_orm.Ado.DataType}-{a.Table.DbName}-{a.Alias}-{a.Type}"))}", s =>
{
@@ -735,7 +735,7 @@ namespace FreeSql.Internal.CommonProvider
};
});
}
- protected GetAllFieldExpressionTreeInfo GetAllFieldExpressionTreeLevel2()
+ public GetAllFieldExpressionTreeInfo GetAllFieldExpressionTreeLevel2()
{
return _dicGetAllFieldExpressionTree.GetOrAdd(string.Join("+", _tables.Select(a => $"{_orm.Ado.DataType}-{a.Table.DbName}-{a.Alias}-{a.Type}")), s =>
{