From 4dd4f232571068ca8969ed83d8b213edc60cb0db Mon Sep 17 00:00:00 2001
From: 28810 <28810@YEXIANGQIN>
Date: Mon, 1 Jun 2020 10:36:34 +0800
Subject: [PATCH] =?UTF-8?q?-=20=E5=A2=9E=E5=8A=A0=20WhereDynamicFilter=20?=
=?UTF-8?q?=E6=93=8D=E4=BD=9C=E7=AC=A6=20Range/Any=EF=BC=8C=E5=AE=9E?=
=?UTF-8?q?=E7=8E=B0=E8=8C=83=E5=9B=B4/In=E6=9F=A5=E8=AF=A2=EF=BC=9B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
FreeSql.DbContext/FreeSql.DbContext.xml | 16 ++
.../Sqlite/Curd/SqliteSelectTest.cs | 38 +++-
FreeSql/FreeSql.xml | 170 +++++++++++++++++-
.../SelectProvider/Select0Provider.cs | 17 +-
FreeSql/Internal/Model/DynamicFilterInfo.cs | 24 ++-
5 files changed, 260 insertions(+), 5 deletions(-)
diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml
index 132d875e..4854f49c 100644
--- a/FreeSql.DbContext/FreeSql.DbContext.xml
+++ b/FreeSql.DbContext/FreeSql.DbContext.xml
@@ -125,6 +125,13 @@
清空状态数据
+
+
+ 根据 lambda 条件删除数据
+
+
+
+
添加
@@ -479,5 +486,14 @@
+
+
+ 批量注入 Repository,可以参考代码自行调整
+
+
+
+
+
+
diff --git a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs
index 577f59bd..d8f7e2bf 100644
--- a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs
@@ -1918,6 +1918,8 @@ WHERE (((cast(a.""Id"" as character)) in (SELECT b.""Title""
public virtual string ParentCode { get; set; }
public DateTime CreateTime { get; set; }
+
+ public int testint { get; set; }
}
[Table(Name = "D_District", DisableSyncStructure = true)]
public class VM_District_Child : BaseDistrict
@@ -1976,12 +1978,44 @@ WHERE (((cast(a.""Id"" as character)) in (SELECT b.""Title""
]
}
")).ToSql();
- Assert.Equal(@"SELECT a.""Code"", a.""Name"", a.""CreateTime"", a.""ParentCode""
+ Assert.Equal(@"SELECT a.""Code"", a.""Name"", a.""CreateTime"", a.""testint"", a.""ParentCode""
FROM ""D_District"" a
WHERE (((a.""Code"") LIKE '%val1%' AND (a.""Name"") LIKE 'val2%' OR (a.""Name"") LIKE '%val3' OR a.""ParentCode"" = 'val4' OR a.""CreateTime"" >= '2010-10-10 00:00:00'))", sql);
sql = fsql.Select().WhereDynamicFilter(JsonConvert.DeserializeObject(@"
{
+ ""Logic"" : ""Or"",
+ ""Filters"" :
+ [
+ {
+ ""Field"" : ""CreateTime"",
+ ""Operator"" : ""Range"",
+ ""Value"" : ""2010-10-10,2010-12-10""
+ },
+ {
+ ""Field"" : ""Name"",
+ ""Operator"" : ""Any"",
+ ""Value"" : ""val1,val2,val3,val4""
+ },
+ {
+ ""Field"" : ""testint"",
+ ""Operator"" : ""Range"",
+ ""Value"" : ""100,555""
+ },
+ {
+ ""Field"" : ""testint"",
+ ""Operator"" : ""Any"",
+ ""Value"" : ""1,5,11,15""
+ }
+ ]
+}
+")).ToSql();
+ Assert.Equal(@"SELECT a.""Code"", a.""Name"", a.""CreateTime"", a.""testint"", a.""ParentCode""
+FROM ""D_District"" a
+WHERE ((a.""CreateTime"" >= '2010-10-10 00:00:00' AND a.""CreateTime"" < '2010-12-10 00:00:00' OR ((a.""Name"") in ('val1','val2','val3','val4')) OR a.""testint"" >= 100 AND a.""testint"" < 555 OR ((a.""testint"") in (1,5,11,15))))", sql);
+
+ sql = fsql.Select().WhereDynamicFilter(JsonConvert.DeserializeObject(@"
+{
""Logic"" : ""Or"",
""Filters"" :
[
@@ -2035,7 +2069,7 @@ WHERE (((a.""Code"") LIKE '%val1%' AND (a.""Name"") LIKE 'val2%' OR (a.""Name"")
]
}
")).ToSql();
- Assert.Equal(@"SELECT a.""Code"", a.""Name"", a.""CreateTime"", a.""ParentCode"", a__Parent.""Code"" as5, a__Parent.""Name"" as6, a__Parent.""CreateTime"" as7, a__Parent.""ParentCode"" as8
+ 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'))", sql);
diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml
index 1808426b..91c6a3fb 100644
--- a/FreeSql/FreeSql.xml
+++ b/FreeSql/FreeSql.xml
@@ -2411,6 +2411,137 @@
+
+
+ 查询,若使用读写分离,查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】
+
+
+
+
+
+
+
+
+ 查询,ExecuteReaderAsync(dr => {}, "select * from user where age > ?age", new { age = 25 })
+
+
+
+
+
+
+ 查询
+
+
+
+
+
+
+ 查询,ExecuteArrayAsync("select * from user where age > ?age", new { age = 25 })
+
+
+
+
+
+
+
+ 查询
+
+
+
+
+
+
+ 查询,ExecuteDataSetAsync("select * from user where age > ?age; select 2", new { age = 25 })
+
+
+
+
+
+
+
+ 查询
+
+
+
+
+
+
+ 查询,ExecuteDataTableAsync("select * from user where age > ?age", new { age = 25 })
+
+
+
+
+
+
+
+ 在【主库】执行
+
+
+
+
+
+
+
+ 在【主库】执行,ExecuteNonQueryAsync("delete from user where age > ?age", new { age = 25 })
+
+
+
+
+
+
+
+ 在【主库】执行
+
+
+
+
+
+
+
+ 在【主库】执行,ExecuteScalarAsync("select 1 from user where age > ?age", new { age = 25 })
+
+
+
+
+
+
+
+ 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > ?age", new SqlParameter { ParameterName = "age", Value = 25 })
+
+
+
+
+
+
+
+
+
+ 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > ?age", new { age = 25 })
+
+
+
+
+
+
+
+
+ 执行SQL返回对象集合,Query<User>("select * from user where age > ?age; select * from address", new SqlParameter { ParameterName = "age", Value = 25 })
+
+
+
+
+
+
+
+
+
+ 执行SQL返回对象集合,Query<User>("select * from user where age > ?age; select * from address", new { age = 25 })
+
+
+
+
+
+
可自定义解析表达式
@@ -2939,9 +3070,22 @@
like
+
+
+ =
+ Equal/Equals/Eq 效果相同
+
+
- =
+ =
+ Equal/Equals/Eq 效果相同
+
+
+
+
+ =
+ Equal/Equals/Eq 效果相同
@@ -2969,6 +3113,18 @@
<=
+
+
+ >= and <
+ 此时 Value 的值格式为逗号分割:value1,value2
+
+
+
+
+ in (1,2,3)
+ 此时 Value 的值格式为逗号分割:value1,value2,value3...
+
+
中间表,多对多
@@ -3013,6 +3169,12 @@
超时
+
+
+ 获取资源
+
+
+
使用完毕后,归还资源
@@ -3083,6 +3245,12 @@
资源对象
+
+
+ 从对象池获取对象成功的时候触发,通过该方法统计或初始化对象
+
+ 资源对象
+
归还对象给对象池的时候触发
diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs
index e4b1a515..b1d550c5 100644
--- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs
+++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs
@@ -1029,6 +1029,8 @@ namespace FreeSql.Internal.CommonProvider
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) });
+ static ConcurrentDictionary MethodEnumerableContainsDic = new ConcurrentDictionary();
+ static MethodInfo GetMethodEnumerableContains(Type elementType) => MethodEnumerableContainsDic.GetOrAdd(elementType, et => typeof(Enumerable).GetMethods().Where(a => a.Name == "Contains").FirstOrDefault().MakeGenericMethod(elementType));
public TSelect WhereDynamicFilter(DynamicFilterInfo filter)
{
if (filter == null) return this as TSelect;
@@ -1089,14 +1091,27 @@ namespace FreeSql.Internal.CommonProvider
case DynamicFilterOperator.NotStartsWith: exp = Expression.Not(Expression.Call(exp, MethodStringStartsWith, Expression.Constant(fi.Value))); break;
case DynamicFilterOperator.NotEndsWith: exp = Expression.Not(Expression.Call(exp, MethodStringEndsWith, Expression.Constant(fi.Value))); break;
+ case DynamicFilterOperator.Eq:
case DynamicFilterOperator.Equals:
- case DynamicFilterOperator.Eq: exp = Expression.Equal(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fi.Value), exp.Type)); break;
+ case DynamicFilterOperator.Equal: exp = Expression.Equal(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fi.Value), exp.Type)); break;
case DynamicFilterOperator.NotEqual: exp = Expression.NotEqual(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fi.Value), exp.Type)); break;
case DynamicFilterOperator.GreaterThan: exp = Expression.GreaterThan(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fi.Value), exp.Type)); break;
case DynamicFilterOperator.GreaterThanOrEqual: exp = Expression.GreaterThanOrEqual(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fi.Value), exp.Type)); break;
case DynamicFilterOperator.LessThan: exp = Expression.LessThan(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fi.Value), exp.Type)); break;
case DynamicFilterOperator.LessThanOrEqual: exp = Expression.LessThanOrEqual(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fi.Value), exp.Type)); break;
+ case DynamicFilterOperator.Range:
+ var fiValueRangeArray = fi.Value.Split(',');
+ if (fiValueRangeArray.Length != 2) throw new ArgumentException($"Range 对应 Value 应该逗号分割,并且长度为 2");
+ exp = Expression.AndAlso(
+ Expression.GreaterThanOrEqual(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fiValueRangeArray[0]), exp.Type)),
+ Expression.LessThan(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fiValueRangeArray[1]), exp.Type)));
+ break;
+ case DynamicFilterOperator.Any:
+ var fiValueAnyArray = fi.Value.Split(',');
+ var fiValueAnyArrayType = exp.Type.MakeArrayType();
+ exp = Expression.Call(GetMethodEnumerableContains(exp.Type), Expression.Constant(Utils.GetDataReaderValue(fiValueAnyArrayType, fiValueAnyArray), fiValueAnyArrayType), exp);
+ break;
}
var sql = _commonExpression.ExpressionWhereLambda(_tables, exp, null, null, _params);
diff --git a/FreeSql/Internal/Model/DynamicFilterInfo.cs b/FreeSql/Internal/Model/DynamicFilterInfo.cs
index 81ffc35e..fac235fa 100644
--- a/FreeSql/Internal/Model/DynamicFilterInfo.cs
+++ b/FreeSql/Internal/Model/DynamicFilterInfo.cs
@@ -55,9 +55,19 @@ namespace FreeSql.Internal.Model
NotEndsWith,
///
- /// =
+ /// =
+ /// Equal/Equals/Eq 效果相同
+ ///
+ Equal,
+ ///
+ /// =
+ /// Equal/Equals/Eq 效果相同
///
Equals,
+ ///
+ /// =
+ /// Equal/Equals/Eq 效果相同
+ ///
Eq,
///
/// <>
@@ -80,5 +90,17 @@ namespace FreeSql.Internal.Model
/// <=
///
LessThanOrEqual,
+
+ ///
+ /// >= and <
+ /// 此时 Value 的值格式为逗号分割:value1,value2
+ ///
+ Range,
+
+ ///
+ /// in (1,2,3)
+ /// 此时 Value 的值格式为逗号分割:value1,value2,value3...
+ ///
+ Any
}
}