From 46bc2189c45b851e766f5eba85135e561c311ef1 Mon Sep 17 00:00:00 2001
From: 28810 <28810@YEXIANGQIN>
Date: Fri, 18 Sep 2020 12:33:07 +0800
Subject: [PATCH] =?UTF-8?q?-=20=E5=A2=9E=E5=8A=A0=20ISelect=20OrderByPrope?=
=?UTF-8?q?rtyName=20=E6=96=B9=E6=B3=95=20#446=20#278=20#380=20#361=20#197?=
=?UTF-8?q?=EF=BC=9B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
FreeSql.DbContext/FreeSql.DbContext.xml | 9 ++
.../Sqlite/Curd/SqliteSelectTest.cs | 61 ++++++++++++
FreeSql/FreeSql.xml | 19 ++++
FreeSql/Interface/Curd/ISelect/ISelect0.cs | 17 ++++
.../SelectProvider/Select0Provider.cs | 93 +++++++++++--------
5 files changed, 161 insertions(+), 38 deletions(-)
diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml
index 9c6cd88b..743835e4 100644
--- a/FreeSql.DbContext/FreeSql.DbContext.xml
+++ b/FreeSql.DbContext/FreeSql.DbContext.xml
@@ -532,5 +532,14 @@
+
+
+ 批量注入 Repository,可以参考代码自行调整
+
+
+
+
+
+
diff --git a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs
index b2d9a63d..3d7caa44 100644
--- a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs
@@ -2304,6 +2304,67 @@ WHERE ((a.""CreateTime"" >= '2010-10-10 00:00:00' AND a.""CreateTime"" < '2010-1
FROM ""D_District"" a
LEFT JOIN ""D_District"" a__Parent ON a__Parent.""Code"" = a.""ParentCode""
WHERE ((not((a.""Code"") LIKE '%val1%') AND not((a.""Name"") LIKE 'val2%') OR not((a.""Name"") LIKE '%val3') OR a.""ParentCode"" <> 'val4' OR a__Parent.""Code"" = 'val11' AND (a__Parent.""Name"") LIKE '%val22%' OR a__Parent.""Name"" = 'val33' OR a__Parent.""ParentCode"" = 'val44'))", sql);
+
+ sql = fsql.Select().OrderByPropertyName("Parent.Name").WhereDynamicFilter(JsonConvert.DeserializeObject(@"
+{
+ ""Logic"" : ""Or"",
+ ""Filters"" :
+ [
+ {
+ ""Field"" : ""Code"",
+ ""Operator"" : ""NotContains"",
+ ""Value"" : ""val1"",
+ ""Filters"" :
+ [
+ {
+ ""Field"" : ""Name"",
+ ""Operator"" : ""NotStartsWith"",
+ ""Value"" : ""val2"",
+ }
+ ]
+ },
+ {
+ ""Field"" : ""Name"",
+ ""Operator"" : ""NotEndsWith"",
+ ""Value"" : ""val3""
+ },
+ {
+ ""Field"" : ""ParentCode"",
+ ""Operator"" : ""NotEqual"",
+ ""Value"" : ""val4""
+ },
+
+ {
+ ""Field"" : ""Parent.Code"",
+ ""Operator"" : ""eq"",
+ ""Value"" : ""val11"",
+ ""Filters"" :
+ [
+ {
+ ""Field"" : ""Parent.Name"",
+ ""Operator"" : ""contains"",
+ ""Value"" : ""val22"",
+ }
+ ]
+ },
+ {
+ ""Field"" : ""Parent.Name"",
+ ""Operator"" : ""eq"",
+ ""Value"" : ""val33""
+ },
+ {
+ ""Field"" : ""Parent.ParentCode"",
+ ""Operator"" : ""eq"",
+ ""Value"" : ""val44""
+ }
+ ]
+}
+")).ToSql();
+ Assert.Equal(@"SELECT a.""Code"", a.""Name"", a.""CreateTime"", a.""testint"", a.""ParentCode"", a__Parent.""Code"" as6, a__Parent.""Name"" as7, a__Parent.""CreateTime"" as8, a__Parent.""testint"" as9, a__Parent.""ParentCode"" as10
+FROM ""D_District"" a
+LEFT JOIN ""D_District"" a__Parent ON a__Parent.""Code"" = a.""ParentCode""
+WHERE ((not((a.""Code"") LIKE '%val1%') AND not((a.""Name"") LIKE 'val2%') OR not((a.""Name"") LIKE '%val3') OR a.""ParentCode"" <> 'val4' OR a__Parent.""Code"" = 'val11' AND (a__Parent.""Name"") LIKE '%val22%' OR a__Parent.""Name"" = 'val33' OR a__Parent.""ParentCode"" = 'val44'))
+ORDER BY a__Parent.""Name""", sql);
}
}
}
diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml
index 79039cd6..b99f558c 100644
--- a/FreeSql/FreeSql.xml
+++ b/FreeSql/FreeSql.xml
@@ -1943,6 +1943,25 @@
参数
+
+
+ 按属性名字符串排序(支持导航属性)
+ 属性名:Name导航属性:Parent.Name多表:b.Name
+
+ 属性名:Name导航属性:Parent.Name多表:b.Name
+ 顺序 | 倒序
+
+
+
+
+ 按属性名字符串排序(支持导航属性)
+ 属性名:Name导航属性:Parent.Name多表:b.Name
+
+ true 时生效
+ 属性名:Name导航属性:Parent.Name多表:b.Name
+ 顺序 | 倒序
+
+
查询向后偏移行数
diff --git a/FreeSql/Interface/Curd/ISelect/ISelect0.cs b/FreeSql/Interface/Curd/ISelect/ISelect0.cs
index 7180b408..4ef554fd 100644
--- a/FreeSql/Interface/Curd/ISelect/ISelect0.cs
+++ b/FreeSql/Interface/Curd/ISelect/ISelect0.cs
@@ -337,6 +337,23 @@ namespace FreeSql
/// 参数
///
TSelect OrderBy(bool condition, string sql, object parms = null);
+ ///
+ /// 按属性名字符串排序(支持导航属性)
+ /// 属性名:Name导航属性:Parent.Name多表:b.Name
+ ///
+ /// 属性名:Name导航属性:Parent.Name多表:b.Name
+ /// 顺序 | 倒序
+ ///
+ TSelect OrderByPropertyName(string property, bool isAscending = true);
+ ///
+ /// 按属性名字符串排序(支持导航属性)
+ /// 属性名:Name导航属性:Parent.Name多表:b.Name
+ ///
+ /// true 时生效
+ /// 属性名:Name导航属性:Parent.Name多表:b.Name
+ /// 顺序 | 倒序
+ ///
+ TSelect OrderByPropertyNameIf(bool condition, string property, bool isAscending = true);
///
/// 查询向后偏移行数
diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs
index 9a67dc82..d8ca14e4 100644
--- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs
+++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs
@@ -442,6 +442,60 @@ namespace FreeSql.Internal.CommonProvider
return this as TSelect;
}
+ public Expression ConvertStringPropertyToExpression(string property)
+ {
+ if (string.IsNullOrEmpty(property)) return null;
+ var field = property.Split('.').Select(a => a.Trim()).ToArray();
+ Expression exp = null;
+
+ if (field.Length == 1)
+ {
+ foreach (var tb in _tables)
+ {
+ if (tb.Table.ColumnsByCs.TryGetValue(field[0], out var col) &&
+ tb.Table.Properties.TryGetValue(field[0], out var prop))
+ {
+ tb.Parameter = Expression.Parameter(tb.Table.Type, tb.Alias);
+ exp = Expression.MakeMemberAccess(tb.Parameter, prop);
+ break;
+ }
+ }
+ if (exp == null) throw new Exception($"无法匹配 {property}");
+ }
+ else
+ {
+ var firstTb = _tables[0];
+ var firstTbs = _tables.Where(a => a.AliasInit == field[0]).ToArray();
+ if (firstTbs.Length == 1) firstTb = firstTbs[0];
+
+ firstTb.Parameter = Expression.Parameter(firstTb.Table.Type, firstTb.Alias);
+ var currentType = firstTb.Table.Type;
+ Expression currentExp = firstTb.Parameter;
+
+ for (var x = 0; x < field.Length; x++)
+ {
+ var tmp1 = field[x];
+ if (_commonUtils.GetTableByEntity(currentType).Properties.TryGetValue(tmp1, out var prop) == false)
+ throw new ArgumentException($"{currentType.DisplayCsharp()} 无法找到属性名 {tmp1}");
+ currentType = prop.PropertyType;
+ currentExp = Expression.MakeMemberAccess(currentExp, prop);
+ }
+ exp = currentExp;
+ }
+ return exp;
+ }
+
+ public TSelect OrderByPropertyName(string property, bool isAscending = true) => OrderByPropertyNameIf(true, property, isAscending);
+ public TSelect OrderByPropertyNameIf(bool condition, string property, bool isAscending = true)
+ {
+ if (condition == false) return this as TSelect;
+ Expression exp = ConvertStringPropertyToExpression(property);
+ if (exp == null) return this as TSelect;
+ var field = _commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null);
+ if (isAscending) return this.OrderBy(field);
+ return this.OrderBy($"{field} DESC");
+ }
+
static MethodInfo MethodStringContains = typeof(string).GetMethod("Contains", new[] { typeof(string) });
static MethodInfo MethodStringStartsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
static MethodInfo MethodStringEndsWith = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
@@ -460,44 +514,7 @@ namespace FreeSql.Internal.CommonProvider
{
if (string.IsNullOrEmpty(fi.Field) == false)
{
- var field = fi.Field.Split('.').Select(a => a.Trim()).ToArray();
- Expression exp = null;
-
- if (field.Length == 1)
- {
- foreach (var tb in _tables)
- {
- if (tb.Table.ColumnsByCs.TryGetValue(field[0], out var col) &&
- tb.Table.Properties.TryGetValue(field[0], out var prop))
- {
- tb.Parameter = Expression.Parameter(tb.Table.Type, tb.Alias);
- exp = Expression.MakeMemberAccess(tb.Parameter, prop);
- break;
- }
- }
- if (exp == null) throw new Exception($"无法匹配 {fi.Field}");
- }
- else
- {
- var firstTb = _tables[0];
- var firstTbs = _tables.Where(a => a.AliasInit == field[0]).ToArray();
- if (firstTbs.Length == 1) firstTb = firstTbs[0];
-
- firstTb.Parameter = Expression.Parameter(firstTb.Table.Type, firstTb.Alias);
- var currentType = firstTb.Table.Type;
- Expression currentExp = firstTb.Parameter;
-
- for (var x = 0; x < field.Length; x++)
- {
- var tmp1 = field[x];
- if (_commonUtils.GetTableByEntity(currentType).Properties.TryGetValue(tmp1, out var prop) == false)
- throw new ArgumentException($"{currentType.DisplayCsharp()} 无法找到属性名 {tmp1}");
- currentType = prop.PropertyType;
- currentExp = Expression.MakeMemberAccess(currentExp, prop);
- }
- exp = currentExp;
- }
-
+ Expression exp = ConvertStringPropertyToExpression(fi.Field);
switch (fi.Operator)
{
case DynamicFilterOperator.Contains: exp = Expression.Call(exp, MethodStringContains, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fi.Value?.ToString()), exp.Type)); break;