mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-06-19 20:38:16 +08:00
- 增加 ISelect.WhereDynamicFilter 方法实现动态过滤条件(与前端交互);
This commit is contained in:
@ -1025,6 +1025,111 @@ namespace FreeSql.Internal.CommonProvider
|
||||
if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(sql, parms));
|
||||
return this as TSelect;
|
||||
}
|
||||
|
||||
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) });
|
||||
public TSelect WhereDynamicFilter(DynamicFilterInfo filter)
|
||||
{
|
||||
if (filter == null) return this as TSelect;
|
||||
var sb = new StringBuilder();
|
||||
ParseFilter(DynamicFilterLogic.And, filter, true);
|
||||
this.Where(sb.ToString());
|
||||
sb.Clear();
|
||||
return this as TSelect;
|
||||
|
||||
void ParseFilter(DynamicFilterLogic logic, DynamicFilterInfo fi, bool isend)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
switch (fi.Operator)
|
||||
{
|
||||
case DynamicFilterOperator.Contains: exp = Expression.Call(exp, MethodStringContains, Expression.Constant(fi.Value)); break;
|
||||
case DynamicFilterOperator.StartsWith: exp = Expression.Call(exp, MethodStringStartsWith, Expression.Constant(fi.Value)); break;
|
||||
case DynamicFilterOperator.EndsWith: exp = Expression.Call(exp, MethodStringEndsWith, Expression.Constant(fi.Value)); break;
|
||||
case DynamicFilterOperator.NotContains: exp = Expression.Not(Expression.Call(exp, MethodStringContains, Expression.Constant(fi.Value))); break;
|
||||
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.Equals:
|
||||
case DynamicFilterOperator.Eq: 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;
|
||||
}
|
||||
|
||||
var sql = _commonExpression.ExpressionWhereLambda(_tables, exp, null, null, _params);
|
||||
|
||||
sb.Append(sql);
|
||||
}
|
||||
if (fi.Filters?.Any() == true)
|
||||
{
|
||||
if (string.IsNullOrEmpty(fi.Field) == false)
|
||||
sb.Append(" AND ");
|
||||
if (fi.Logic == DynamicFilterLogic.Or) sb.Append("(");
|
||||
for (var x = 0; x < fi.Filters.Count; x++)
|
||||
ParseFilter(fi.Logic, fi.Filters[x], x == fi.Filters.Count - 1);
|
||||
if (fi.Logic == DynamicFilterLogic.Or) sb.Append(")");
|
||||
}
|
||||
|
||||
if (isend == false)
|
||||
{
|
||||
if (string.IsNullOrEmpty(fi.Field) == false || fi.Filters?.Any() == true)
|
||||
{
|
||||
switch (filter.Logic)
|
||||
{
|
||||
case DynamicFilterLogic.And: sb.Append(" AND "); break;
|
||||
case DynamicFilterLogic.Or: sb.Append(" OR "); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TSelect DisableGlobalFilter(params string[] name)
|
||||
{
|
||||
if (_whereGlobalFilter.Any() == false) return this as TSelect;
|
||||
|
84
FreeSql/Internal/Model/DynamicFilterInfo.cs
Normal file
84
FreeSql/Internal/Model/DynamicFilterInfo.cs
Normal file
@ -0,0 +1,84 @@
|
||||
using FreeSql;
|
||||
using FreeSql.Internal;
|
||||
using FreeSql.Internal.CommonProvider;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace FreeSql.Internal.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 动态过滤条件
|
||||
/// </summary>
|
||||
public class DynamicFilterInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 属性名:Name<para></para>
|
||||
/// 导航属性:Parent.Name<para></para>
|
||||
/// 多表:b.Name<para></para>
|
||||
/// </summary>
|
||||
public string Field { get; set; }
|
||||
/// <summary>
|
||||
/// 操作符
|
||||
/// </summary>
|
||||
public DynamicFilterOperator Operator { get; set; }
|
||||
/// <summary>
|
||||
/// 值
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Filters 下的逻辑运算符
|
||||
/// </summary>
|
||||
public DynamicFilterLogic Logic { get; set; }
|
||||
/// <summary>
|
||||
/// 子过滤条件,它与当前的逻辑关系是 And<para></para>
|
||||
/// 注意:当前 Field 可以留空
|
||||
/// </summary>
|
||||
public List<DynamicFilterInfo> Filters { get; set; }
|
||||
}
|
||||
|
||||
public enum DynamicFilterLogic { And, Or }
|
||||
public enum DynamicFilterOperator
|
||||
{
|
||||
/// <summary>
|
||||
/// like
|
||||
/// </summary>
|
||||
Contains,
|
||||
StartsWith,
|
||||
EndsWith,
|
||||
NotContains,
|
||||
NotStartsWith,
|
||||
NotEndsWith,
|
||||
|
||||
/// <summary>
|
||||
/// =
|
||||
/// </summary>
|
||||
Equals,
|
||||
Eq,
|
||||
/// <summary>
|
||||
/// <>
|
||||
/// </summary>
|
||||
NotEqual,
|
||||
|
||||
/// <summary>
|
||||
/// >
|
||||
/// </summary>
|
||||
GreaterThan,
|
||||
/// <summary>
|
||||
/// >=
|
||||
/// </summary>
|
||||
GreaterThanOrEqual,
|
||||
/// <summary>
|
||||
/// <
|
||||
/// </summary>
|
||||
LessThan,
|
||||
/// <summary>
|
||||
/// <=
|
||||
/// </summary>
|
||||
LessThanOrEqual,
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user