From 0ec4353e829f2175e0f22a05aa5c5f151cc0a546 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=7E=7E=E7=A9=BA=E4=B8=80=7E=7E?= <407931232@qq.com>
Date: Sun, 17 Nov 2024 20:23:00 +0800
Subject: [PATCH] =?UTF-8?q?DynamicFilterInfo=E6=96=B0=E5=A2=9EUseAllLogic?=
 =?UTF-8?q?=EF=BC=8C=E4=BD=BF=E7=94=A8=E6=89=80=E6=9C=89=E9=80=BB=E8=BE=91?=
 =?UTF-8?q?=E8=BF=90=E7=AE=97=E7=AC=A6=E7=9A=84=E6=A8=A1=E5=BC=8F=EF=BC=8C?=
 =?UTF-8?q?=E9=BB=98=E8=AE=A4=E4=B8=BAFalse=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

False:按照原来的模式,只有分组的逻辑运算符会生成到查询条件中,只有OR分组会生成括号。

True:按照新的模式,所有的逻辑运算符都会生成到查询条件中,所有分组(AND或OR)都会生成括号。

WhereDynamicFilter(DynamicFilterInfo filter)中保留原有模式,并增加了对新模式的处理。
---
 FreeSql.DbContext/FreeSql.DbContext.xml       |   8 -
 FreeSql/FreeSql.xml                           | 269 ++++++++++--------
 .../SelectProvider/Select0Provider.cs         | 155 ++++++++--
 FreeSql/Internal/Model/DynamicFilterInfo.cs   |  27 +-
 4 files changed, 305 insertions(+), 154 deletions(-)

diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml
index c941a15d9..a7a94fcda 100644
--- a/FreeSql.DbContext/FreeSql.DbContext.xml
+++ b/FreeSql.DbContext/FreeSql.DbContext.xml
@@ -758,13 +758,5 @@
             <param name="that"></param>
             <returns></returns>
         </member>
-        <member name="M:Microsoft.Extensions.DependencyInjection.FreeSqlRepositoryDependencyInjection.AddFreeRepository(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Reflection.Assembly[])">
-            <summary>
-            批量注入 Repository,可以参考代码自行调整
-            </summary>
-            <param name="services"></param>
-            <param name="assemblies"></param>
-            <returns></returns>
-        </member>
     </members>
 </doc>
diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml
index fdde4800e..3805d19fa 100644
--- a/FreeSql/FreeSql.xml
+++ b/FreeSql/FreeSql.xml
@@ -1087,6 +1087,93 @@
             </summary>
             <returns></returns>
         </member>
+        <member name="T:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder">
+            <summary>
+            动态创建实体类型
+            </summary>
+        </member>
+        <member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.#ctor(IFreeSql,System.String,System.Attribute[])">
+            <summary>
+            配置Class
+            </summary>
+            <param name="className">类名</param>
+            <param name="attributes">类标记的特性[Table(Name = "xxx")] [Index(xxxx)]</param>
+            <returns></returns>
+        </member>
+        <member name="P:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.TypeBuilder">
+            <summary>
+            获取类型构建器,可作为要构建的Type来引用
+            </summary>
+        </member>
+        <member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.Property(System.String,System.Type,System.Attribute[])">
+            <summary>
+            配置属性
+            </summary>
+            <param name="propertyName">属性名称</param>
+            <param name="propertyType">属性类型</param>
+            <param name="attributes">属性标记的特性-支持多个</param>
+            <returns></returns>
+        </member>
+        <member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.Property(System.String,System.Type,System.Boolean,System.Attribute[])">
+            <summary>
+            配置属性
+            </summary>
+            <param name="propertyName">属性名称</param>
+            <param name="propertyType">属性类型</param>
+            <param name="isOverride">该属性是否重写父类属性</param>
+            <param name="attributes">属性标记的特性-支持多个</param>
+            <returns></returns>
+        </member>
+        <member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.Property(System.String,System.Type,System.Boolean,System.Object,System.Attribute[])">
+            <summary>
+            配置属性
+            </summary>
+            <param name="propertyName">属性名称</param>
+            <param name="propertyType">属性类型</param>
+            <param name="isOverride">该属性是否重写父类属性</param>
+            <param name="defaultValue">属性默认值</param>
+            <param name="attributes">属性标记的特性-支持多个</param>
+            <returns></returns>
+        </member>
+        <member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.Extend(System.Type)">
+            <summary>
+            配置父类
+            </summary>
+            <param name="superClass">父类类型</param>
+            <returns></returns>
+        </member>
+        <member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.OverrideProperty(System.Reflection.Emit.TypeBuilder@,System.Reflection.Emit.MethodBuilder,FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.PropertyMethodEnum,System.String)">
+            <summary>
+            Override属性
+            </summary>
+            <param name="typeBuilder"></param>
+        </member>
+        <member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.Build">
+            <summary>
+            Emit动态创建出Class - Type
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.BuildJustType">
+            <summary>
+            Emit动态创建出Class - Type,不附带获取TableInfo
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.FirstCharToLower(System.String)">
+            <summary>
+            首字母小写
+            </summary>
+            <param name="input"></param>
+            <returns></returns>
+        </member>
+        <member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.FirstCharToUpper(System.String)">
+            <summary>
+            首字母大写
+            </summary>
+            <param name="input"></param>
+            <returns></returns>
+        </member>
         <member name="M:FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetEntityKeyString(IFreeSql,System.Type,System.Object,System.Boolean,System.String)">
             <summary>
             获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时,返回 ""
@@ -4615,6 +4702,13 @@
             动态过滤条件
             </summary>
         </member>
+        <member name="P:FreeSql.Internal.Model.DynamicFilterInfo.UseAllLogic">
+            <summary>
+            使用所有逻辑运算符,默认为False。
+            False:按照原来的模式,只有分组的逻辑运算符会生成到查询条件中,只有OR分组会生成括号。
+            True:按照新的模式,所有的逻辑运算符都会生成到查询条件中,所有分组(AND或OR)都会生成括号。
+            </summary>
+        </member>
         <member name="P:FreeSql.Internal.Model.DynamicFilterInfo.Field">
             <summary>
             属性名:Name<para></para>
@@ -5810,6 +5904,28 @@
             对象池
             </summary>
         </member>
+        <member name="M:FreeSqlGlobalDynamicEntityExtensions.DynamicEntity(FreeSql.ICodeFirst,System.String,System.Attribute[])">
+            <summary>
+            动态构建Class Type
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:FreeSqlGlobalDynamicEntityExtensions.CreateInstance(FreeSql.Internal.Model.TableInfo,System.Collections.Generic.Dictionary{System.String,System.Object})">
+            <summary>
+            根据字典,创建 table 对应的实体对象
+            </summary>
+            <param name="table"></param>
+            <param name="dict"></param>
+            <returns></returns>
+        </member>
+        <member name="M:FreeSqlGlobalDynamicEntityExtensions.CreateDictionary(FreeSql.Internal.Model.TableInfo,System.Object)">
+            <summary>
+            根据实体对象,创建 table 对应的字典
+            </summary>
+            <param name="table"></param>
+            <param name="instance"></param>
+            <returns></returns>
+        </member>
         <member name="M:FreeSqlGlobalExpressionCallExtensions.Between(System.DateTime,System.DateTime,System.DateTime)">
             <summary>
             C#: that >= between &amp;&amp; that &lt;= and<para></para>
@@ -5831,6 +5947,36 @@
             <param name="end"></param>
             <returns></returns>
         </member>
+        <member name="M:FreeSqlGlobalExpressionCallExtensions.In``1(``0,``0)">
+            <summary>
+            field IN (value1)
+            </summary>
+        </member>
+        <member name="M:FreeSqlGlobalExpressionCallExtensions.In``1(``0,``0,``0)">
+            <summary>
+            field in (value1, value2)
+            </summary>
+        </member>
+        <member name="M:FreeSqlGlobalExpressionCallExtensions.In``1(``0,``0,``0,``0)">
+            <summary>
+            field in (value1, value2, value3)
+            </summary>
+        </member>
+        <member name="M:FreeSqlGlobalExpressionCallExtensions.In``1(``0,``0,``0,``0,``0)">
+            <summary>
+            field in (value1, value2, value3, value4)
+            </summary>
+        </member>
+        <member name="M:FreeSqlGlobalExpressionCallExtensions.In``1(``0,``0,``0,``0,``0,``0)">
+            <summary>
+            field in (value1, value2, value3, value4, value5)
+            </summary>
+        </member>
+        <member name="M:FreeSqlGlobalExpressionCallExtensions.In``1(``0,``0[])">
+            <summary>
+            field in (values)
+            </summary>
+        </member>
         <member name="M:FreeSqlGlobalExtensions.DisplayCsharp(System.Type,System.Boolean)">
             <summary>
             获取 Type 的原始 c# 文本表示
@@ -6346,126 +6492,3 @@
         </member>
     </members>
 </doc>
-<returns></returns>
-        </member>
-        <member name="M:IFreeSql.Insert``1(System.Collections.Generic.List{``0})">
-            <summary>
-            插入数据,传入实体集合
-            </summary>
-            <typeparam name="T1"></typeparam>
-            <param name="source"></param>
-            <returns></returns>
-        </member>
-        <member name="M:IFreeSql.Insert``1(System.Collections.Generic.IEnumerable{``0})">
-            <summary>
-            插入数据,传入实体集合
-            </summary>
-            <typeparam name="T1"></typeparam>
-            <param name="source"></param>
-            <returns></returns>
-        </member>
-        <member name="M:IFreeSql.InsertOrUpdate``1">
-            <summary>
-            插入或更新数据,此功能依赖数据库特性(低版本可能不支持),参考如下:<para></para>
-            MySql 5.6+: on duplicate key update<para></para>
-            PostgreSQL 9.4+: on conflict do update<para></para>
-            SqlServer 2008+: merge into<para></para>
-            Oracle 11+: merge into<para></para>
-            Sqlite: replace into<para></para>
-            DuckDB: on conflict do update<para></para>
-            达梦: merge into<para></para>
-            人大金仓:on conflict do update<para></para>
-            神通:merge into<para></para>
-            MsAccess:不支持<para></para>
-            注意区别:FreeSql.Repository 仓储也有 InsertOrUpdate 方法(不依赖数据库特性)
-            </summary>
-            <typeparam name="T1"></typeparam>
-            <returns></returns>
-        </member>
-        <member name="M:IFreeSql.Update``1">
-            <summary>
-            修改数据
-            </summary>
-            <typeparam name="T1"></typeparam>
-            <returns></returns>
-        </member>
-        <member name="M:IFreeSql.Update``1(System.Object)">
-            <summary>
-            修改数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
-            </summary>
-            <typeparam name="T1"></typeparam>
-            <param name="dywhere">主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合</param>
-            <returns></returns>
-        </member>
-        <member name="M:IFreeSql.Select``1">
-            <summary>
-            查询数据
-            </summary>
-            <typeparam name="T1"></typeparam>
-            <returns></returns>
-        </member>
-        <member name="M:IFreeSql.Select``1(System.Object)">
-            <summary>
-            查询数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
-            </summary>
-            <typeparam name="T1"></typeparam>
-            <param name="dywhere">主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合</param>
-            <returns></returns>
-        </member>
-        <member name="M:IFreeSql.Delete``1">
-            <summary>
-            删除数据
-            </summary>
-            <typeparam name="T1"></typeparam>
-            <returns></returns>
-        </member>
-        <member name="M:IFreeSql.Delete``1(System.Object)">
-            <summary>
-            删除数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
-            </summary>
-            <typeparam name="T1"></typeparam>
-            <param name="dywhere">主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合</param>
-            <returns></returns>
-        </member>
-        <member name="M:IFreeSql.Transaction(System.Action)">
-            <summary>
-            开启事务(不支持异步)<para></para>
-            v1.5.0 关闭了线程事务超时自动提交的机制
-            </summary>
-            <param name="handler">事务体 () => {}</param>
-        </member>
-        <member name="M:IFreeSql.Transaction(System.Data.IsolationLevel,System.Action)">
-            <summary>
-            开启事务(不支持异步)<para></para>
-            v1.5.0 关闭了线程事务超时自动提交的机制
-            </summary>
-            <param name="isolationLevel"></param>
-            <param name="handler">事务体 () => {}</param>
-        </member>
-        <member name="P:IFreeSql.Ado">
-            <summary>
-            数据库访问对象
-            </summary>
-        </member>
-        <member name="P:IFreeSql.Aop">
-            <summary>
-            所有拦截方法都在这里
-            </summary>
-        </member>
-        <member name="P:IFreeSql.CodeFirst">
-            <summary>
-            CodeFirst 模式开发相关方法
-            </summary>
-        </member>
-        <member name="P:IFreeSql.DbFirst">
-            <summary>
-            DbFirst 模式开发相关方法
-            </summary>
-        </member>
-        <member name="P:IFreeSql.GlobalFilter">
-            <summary>
-            全局过滤设置,可默认附加为 Select/Update/Delete 条件
-            </summary>
-        </member>
-    </members>
-</doc>
diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs
index 1d65a44ca..a81d5c9f1 100644
--- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs
+++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs
@@ -60,7 +60,8 @@ public Select0Provider()
             _paramsInit = _params;
         }
 
-        int _disposeCounter;
+        private int _disposeCounter;
+
         ~Select0Provider()
         {
             if (Interlocked.Increment(ref _disposeCounter) != 1) return;
@@ -83,6 +84,7 @@ public Select0Provider()
         }
 
         public abstract string ToSqlBase(string field = null);
+
         public abstract void AsTableBase(Func<Type, string, string> tableRule);
 
         public static void CopyData(Select0Provider from, Select0Provider to, ReadOnlyCollection<ParameterExpression> lambParms)
@@ -163,6 +165,7 @@ internal class WithTempQueryParser : BaseDiyMemberExpression
         {
             public List<InsideInfo> _insideSelectList = new List<InsideInfo>();
             public List<SelectTableInfo> _outsideTable = new List<SelectTableInfo>();
+
             public WithTempQueryParser(Select0Provider insideSelect, SelectGroupingProvider insideSelectGroup, Expression selector, SelectTableInfo outsideTable)
             {
                 if (selector != null)
@@ -171,6 +174,7 @@ public WithTempQueryParser(Select0Provider insideSelect, SelectGroupingProvider
                     _outsideTable.Add(outsideTable);
                 }
             }
+
             public class InsideInfo
             {
                 public Select0Provider InsideSelect { get; }
@@ -238,6 +242,7 @@ public WithTempQueryParser Append(Select0Provider select, SelectTableInfo outsid
             }
 
             public SelectTableInfo ParseExpMatchedTable { get; private set; }
+
             public override string ParseExp(Expression[] members)
             {
                 ParseExpMapResult = null;
@@ -270,6 +275,7 @@ public override string ParseExp(Expression[] members)
                 ParseExpMapResult = read;
                 return $"{ParseExpMatchedTable.Alias}.{read.DbNestedField}";
             }
+
             public SelectTableInfo GetOutsideSelectTable(ParameterExpression parameterExp)
             {
                 if (parameterExp == null) return null;
@@ -285,6 +291,7 @@ public SelectTableInfo GetOutsideSelectTable(ParameterExpression parameterExp)
 
         public static MethodInfo _methodSqlExtInternalRawField = typeof(SqlExt).GetMethod("InternalRawField", BindingFlags.NonPublic | BindingFlags.Static);
         public static MethodInfo _methodSqlExtInternalRawSql = typeof(SqlExt).GetMethod("InternalRawSql", BindingFlags.NonPublic | BindingFlags.Static);
+
         public Expression ConvertStringPropertyToExpression(string property, bool fromFirstTable = false)
         {
             if (string.IsNullOrEmpty(property)) return null;
@@ -343,6 +350,7 @@ public Expression ConvertStringPropertyToExpression(string property, bool fromFi
         }
 
         public static MethodInfo _MethodDataReaderIsDBNull = typeof(DbDataReader).GetMethod("IsDBNull", new Type[] { typeof(int) });
+
         public static Dictionary<Type, MethodInfo> _dicMethodDataReaderGetValue = new Dictionary<Type, MethodInfo>
         {
             [typeof(bool)] = typeof(DbDataReader).GetMethod("GetBoolean", new Type[] { typeof(int) }),
@@ -355,12 +363,14 @@ public Expression ConvertStringPropertyToExpression(string property, bool fromFi
             [typeof(string)] = typeof(DbDataReader).GetMethod("GetString", new Type[] { typeof(int) }),
             //[typeof(Guid)] = typeof(DbDataReader).GetMethod("GetGuid", new Type[] { typeof(int) }) 有些驱动不兼容
         };
+
         public static Dictionary<DataType, Dictionary<Type, MethodInfo>> _dicMethodDataReaderGetValueOverride = new Dictionary<DataType, Dictionary<Type, MethodInfo>>();
 
         public static MethodInfo MethodStringContains = typeof(string).GetMethod("Contains", new[] { typeof(string) });
         public static MethodInfo MethodStringStartsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
         public static MethodInfo MethodStringEndsWith = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
-        static ConcurrentDictionary<string, MethodInfo> MethodEnumerableDic = new ConcurrentDictionary<string, MethodInfo>();
+        private static ConcurrentDictionary<string, MethodInfo> MethodEnumerableDic = new ConcurrentDictionary<string, MethodInfo>();
+
         public static MethodInfo GetMethodEnumerable(string methodName) => MethodEnumerableDic.GetOrAdd(methodName, et =>
         {
             var methods = typeof(Enumerable).GetMethods().Where(a => a.Name == et);
@@ -370,6 +380,7 @@ public static MethodInfo GetMethodEnumerable(string methodName) => MethodEnumera
         });
 
         public List<NativeTuple<string, DbParameter[], ReadAnonymousTypeOtherInfo>> _SameSelectPendingShareData;
+
         internal Select0Provider SetSameSelectPendingShareData(List<NativeTuple<string, DbParameter[], ReadAnonymousTypeOtherInfo>> data)
         {
             _SameSelectPendingShareData = data;
@@ -383,6 +394,7 @@ internal Select0Provider SetSameSelectPendingShareData(List<NativeTuple<string,
             }
             return this;
         }
+
         internal bool SameSelectPending(ref string sql, ReadAnonymousTypeOtherInfo csspsod)
         {
             if (_SameSelectPendingShareData != null)
@@ -404,6 +416,7 @@ internal bool SameSelectPending(ref string sql, ReadAnonymousTypeOtherInfo cssps
             }
             return false;
         }
+
         internal static Expression SetSameSelectPendingShareDataWithExpression(Expression exp, List<NativeTuple<string, DbParameter[], ReadAnonymousTypeOtherInfo>> data)
         {
             var callExp = exp as MethodCallExpression;
@@ -449,6 +462,7 @@ public ReadAnonymousTypeAfInfo GetExpressionField(Expression newexp, FieldAliasO
             _commonExpression.ReadAnonymousField(_tables, _tableRule, field, map, ref index, newexp, this, _diymemexpWithTempQuery, _whereGlobalFilter, null, null, true);
             return new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null);
         }
+
         public string GetNestSelectSql(Expression select, string affield, Func<string, string> ToSql)
         {
             var allMemExps = new FindAllMemberExpressionVisitor(this);
@@ -481,10 +495,12 @@ public string GetNestSelectSql(Expression select, string affield, Func<string, s
             field.Clear();
             return sql;
         }
+
         public class FindAllMemberExpressionVisitor : ExpressionVisitor
         {
             public List<NativeTuple<MemberExpression, ColumnInfo>> Result { get; set; } = new List<NativeTuple<MemberExpression, ColumnInfo>>();
-            Select0Provider _select;
+            private Select0Provider _select;
+
             public FindAllMemberExpressionVisitor(Select0Provider select) => _select = select;
 
             protected override Expression VisitMember(MemberExpression node)
@@ -535,10 +551,12 @@ protected override Expression VisitMember(MemberExpression node)
                 return base.VisitMember(node);
             }
         }
+
         public class ReplaceMemberExpressionVisitor : ExpressionVisitor
         {
-            Expression _findExp;
-            Expression _replaceExp;
+            private Expression _findExp;
+            private Expression _replaceExp;
+
             public Expression Replace(Expression exp, Expression find, Expression replace) // object repval)
             {
                 _findExp = find;
@@ -546,6 +564,7 @@ public Expression Replace(Expression exp, Expression find, Expression replace) /
                 //_replaceExp = Expression.Constant(repval, find.Type);
                 return this.Visit(exp);
             }
+
             protected override Expression VisitMember(MemberExpression node)
             {
                 if (_findExp == node) return _replaceExp;
@@ -586,17 +605,20 @@ public TSelect WithTransaction(DbTransaction transaction)
             if (transaction != null) _connection = transaction.Connection;
             return this as TSelect;
         }
+
         public TSelect WithConnection(DbConnection connection)
         {
             if (_transaction?.Connection != connection) _transaction = null;
             _connection = connection;
             return this as TSelect;
         }
+
         public TSelect WithParameters(List<DbParameter> parameters)
         {
             if (parameters != null) _params = parameters;
             return this as TSelect;
         }
+
         public TSelect CommandTimeout(int timeout)
         {
             _commandTimeout = timeout;
@@ -611,6 +633,7 @@ public TSelect GroupBy(string sql, object parms = null)
             if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(_groupby, parms));
             return this as TSelect;
         }
+
         public TSelect Having(string sql, object parms = null)
         {
             if (string.IsNullOrEmpty(_groupby) || string.IsNullOrEmpty(sql)) return this as TSelect;
@@ -625,18 +648,21 @@ public TSelect LeftJoin(Expression<Func<T1, bool>> exp)
             _tables[0].Parameter = exp.Parameters[0];
             return this.InternalJoin(exp?.Body, SelectTableInfoType.LeftJoin);
         }
+
         public TSelect InnerJoin(Expression<Func<T1, bool>> exp)
         {
             if (exp == null) return this as TSelect;
             _tables[0].Parameter = exp.Parameters[0];
             return this.InternalJoin(exp?.Body, SelectTableInfoType.InnerJoin);
         }
+
         public TSelect RightJoin(Expression<Func<T1, bool>> exp)
         {
             if (exp == null) return this as TSelect;
             _tables[0].Parameter = exp.Parameters[0];
             return this.InternalJoin(exp?.Body, SelectTableInfoType.RightJoin);
         }
+
         public TSelect LeftJoin<T2>(Expression<Func<T1, T2, bool>> exp)
         {
             if (exp == null) return this as TSelect;
@@ -644,6 +670,7 @@ public TSelect LeftJoin<T2>(Expression<Func<T1, T2, bool>> exp)
             if (_tables.Count > 1 && _tables[1].Table.Type == typeof(T2)) _tables[1].Parameter = exp.Parameters[1];
             return this.InternalJoin(exp?.Body, SelectTableInfoType.LeftJoin);
         }
+
         public TSelect InnerJoin<T2>(Expression<Func<T1, T2, bool>> exp)
         {
             if (exp == null) return this as TSelect;
@@ -651,6 +678,7 @@ public TSelect InnerJoin<T2>(Expression<Func<T1, T2, bool>> exp)
             if (_tables.Count > 1 && _tables[1].Table.Type == typeof(T2)) _tables[1].Parameter = exp.Parameters[1];
             return this.InternalJoin(exp?.Body, SelectTableInfoType.InnerJoin);
         }
+
         public TSelect RightJoin<T2>(Expression<Func<T1, T2, bool>> exp)
         {
             if (exp == null) return this as TSelect;
@@ -666,6 +694,7 @@ public TSelect InnerJoin(string sql, object parms = null)
             if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(sql, parms));
             return this as TSelect;
         }
+
         public TSelect LeftJoin(string sql, object parms = null)
         {
             if (string.IsNullOrEmpty(sql)) return this as TSelect;
@@ -673,6 +702,7 @@ public TSelect LeftJoin(string sql, object parms = null)
             if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(sql, parms));
             return this as TSelect;
         }
+
         public TSelect RightJoin(string sql, object parms = null)
         {
             if (string.IsNullOrEmpty(sql)) return this as TSelect;
@@ -680,6 +710,7 @@ public TSelect RightJoin(string sql, object parms = null)
             if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(sql, parms));
             return this as TSelect;
         }
+
         public TSelect RawJoin(string sql)
         {
             if (string.IsNullOrEmpty(sql)) return this as TSelect;
@@ -700,14 +731,17 @@ public TSelect Limit(int limit)
             _limit = limit;
             return this as TSelect;
         }
+
         public TSelect Master()
         {
             _select = $" {_select.Trim()} ";
             return this as TSelect;
         }
+
         public TSelect Offset(int offset) => this.Skip(offset) as TSelect;
 
         public TSelect OrderBy(string sql, object parms = null) => this.OrderBy(true, sql, parms);
+
         public TSelect OrderBy(bool condition, string sql, object parms = null)
         {
             if (condition == false) return this as TSelect;
@@ -721,6 +755,7 @@ public TSelect OrderBy(bool condition, string sql, object parms = null)
             if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(sql, parms));
             return this as TSelect;
         }
+
         public TSelect Page(int pageNumber, int pageSize)
         {
             this.Skip(Math.Max(0, pageNumber - 1) * pageSize);
@@ -739,6 +774,7 @@ public TSelect Skip(int offset)
             _skip = offset;
             return this as TSelect;
         }
+
         public TSelect Take(int limit) => this.Limit(limit) as TSelect;
 
         public TSelect Distinct()
@@ -747,7 +783,7 @@ public TSelect Distinct()
             return this as TSelect;
         }
 
-        string GetToDeleteWhere(string alias)
+        private string GetToDeleteWhere(string alias)
         {
             var pks = _tables[0].Table.Primarys;
             var old_selectVal = _select;
@@ -760,6 +796,7 @@ string GetToDeleteWhere(string alias)
                 case DataType.Firebird:
                 case DataType.GBase:
                     break;
+
                 default:
                     _select = "SELECT ";
                     break;
@@ -794,6 +831,7 @@ string GetToDeleteWhere(string alias)
                 _select = old_selectVal;
             }
         }
+
         public IDelete<T1> ToDelete()
         {
             if (_tables[0].Table.Primarys.Any() == false) throw new Exception(CoreErrorStrings.Entity_Must_Primary_Key("ToDelete", _tables[0].Table.CsName));
@@ -816,6 +854,7 @@ public IDelete<T1> ToDelete()
                 case DataType.Firebird:
                 case DataType.GBase:
                     break;
+
                 default:
                     var beforeSql = this._select;
                     if (beforeSql.EndsWith("SELECT ", StringComparison.OrdinalIgnoreCase))
@@ -828,6 +867,7 @@ public IDelete<T1> ToDelete()
             }
             return del.Where(GetToDeleteWhere("ftb_del"));
         }
+
         public IUpdate<T1> ToUpdate()
         {
             if (_tables[0].Table.Primarys.Any() == false) throw new Exception(CoreErrorStrings.Entity_Must_Primary_Key("ToUpdate", _tables[0].Table.CsName));
@@ -850,6 +890,7 @@ public IUpdate<T1> ToUpdate()
                 case DataType.Firebird:
                 case DataType.GBase:
                     break;
+
                 default:
                     var beforeSql = this._select;
                     if (beforeSql.EndsWith("SELECT ", StringComparison.OrdinalIgnoreCase))
@@ -993,7 +1034,9 @@ string[] LocalGetTableNames(SelectTableInfo tb)
             }
             return unions;
         }
+
         public override void AsTableBase(Func<Type, string, string> tableRule) => AsTable(tableRule);
+
         public TSelect AsTable(Func<Type, string, string> tableRule)
         {
             if (_tableRules.Count == 1 && _diymemexpWithTempQuery != null && _diymemexpWithTempQuery is WithTempQueryParser tempQueryParser)
@@ -1011,11 +1054,13 @@ public TSelect AsTable(Func<Type, string, string> tableRule)
             if (tableRule != null) _tableRules.Add(tableRule);
             return this as TSelect;
         }
+
         public TSelect AsAlias(Func<Type, string, string> aliasRule)
         {
             if (aliasRule != null) _aliasRule = aliasRule;
             return this as TSelect;
         }
+
         public TSelect AsType(Type entityType)
         {
             if (entityType == typeof(object)) throw new Exception(CoreErrorStrings.TypeAsType_NotSupport_Object("ISelect"));
@@ -1025,10 +1070,13 @@ public TSelect AsType(Type entityType)
             if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(entityType);
             return this as TSelect;
         }
+
         public override string ToSqlBase(string field = null) => ToSql(field);
+
         public abstract string ToSql(string field = null);
 
         public TSelect Where(string sql, object parms = null) => this.WhereIf(true, sql, parms);
+
         public TSelect WhereIf(bool condition, string sql, object parms = null)
         {
             if (condition == false || string.IsNullOrEmpty(sql)) return this as TSelect;
@@ -1038,6 +1086,7 @@ public TSelect WhereIf(bool condition, string sql, object parms = null)
         }
 
         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;
@@ -1053,13 +1102,30 @@ public TSelect WhereDynamicFilter(DynamicFilterInfo filter)
             if (filter == null) return this as TSelect;
             var sb = new StringBuilder();
             if (IsIgnoreFilter(filter)) filter.Field = "";
+
+            //使用新模式的判断条件,只在第一个过滤器设置即可
+            bool useAllLogic = filter.UseAllLogic;
             ParseFilter(DynamicFilterLogic.And, filter, true);
+
+            //新模式下替换可能与括号连在一起的逻辑运算符
+            if (useAllLogic)
+            {
+                sb = sb.Replace("( AND", "(")
+                    .Replace("( OR", "(");
+            }
+
             this.Where(sb.ToString());
             sb.Clear();
             return this as TSelect;
 
             void ParseFilter(DynamicFilterLogic logic, DynamicFilterInfo fi, bool isend)
             {
+                //新模式下使用过滤器自身的逻辑运算符
+                if (useAllLogic)
+                {
+                    logic = fi.Logic;
+                }
+
                 if (string.IsNullOrEmpty(fi.Field) == false)
                 {
                     Expression exp = null;
@@ -1092,6 +1158,7 @@ void ParseFilter(DynamicFilterLogic logic, DynamicFilterInfo fi, bool isend)
                             exp = ConvertStringPropertyToExpression(fi.Field);
                             if (exp.Type != typeof(string)) exp = Expression.TypeAs(exp, typeof(string));
                             break;
+
                         default:
                             exp = ConvertStringPropertyToExpression(fi.Field);
                             if (exp.Type == typeof(object) && fi.Value != null)
@@ -1127,10 +1194,13 @@ void ParseFilter(DynamicFilterLogic logic, DynamicFilterInfo fi, bool isend)
                         case DynamicFilterOperator.Range:
                             var fiValueRangeArray = getFiListValue();
                             if (fiValueRangeArray.Length != 2) throw new ArgumentException(CoreErrorStrings.Range_Comma_Separateda_By2Char);
+
                             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)));
+                            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.DateRange:
                             var fiValueDateRangeArray = getFiListValue();
                             if (fiValueDateRangeArray?.Length != 2) throw new ArgumentException(CoreErrorStrings.DateRange_Comma_Separateda_By2Char);
@@ -1149,7 +1219,9 @@ void ParseFilter(DynamicFilterLogic logic, DynamicFilterInfo fi, bool isend)
                             exp = Expression.AndAlso(
                                 Expression.GreaterThanOrEqual(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fiValueDateRangeArray[0]), exp.Type)),
                                 Expression.LessThan(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fiValueDateRangeArray[1]), exp.Type)));
+
                             break;
+
                         case DynamicFilterOperator.Any:
                         case DynamicFilterOperator.NotAny:
                             var fiValueAnyArray = getFiListValue();
@@ -1198,6 +1270,10 @@ string[] getFiListValue()
                     }
 
                     var sql = _commonExpression.ExpressionWhereLambda(_tables, _tableRule, exp, _diymemexpWithTempQuery, null, _params);
+                    if (useAllLogic)
+                    {
+                        sql = " " + fi.Logic.ToString().ToUpper() + " " + sql;
+                    }
 
                     sb.Append(sql);
                 }
@@ -1207,16 +1283,33 @@ string[] getFiListValue()
 
                     if (fi.Filters.Any())
                     {
-                        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 (useAllLogic)
+                        {
+                            //第一个条件不用添加逻辑运算符
+                            if (fi != filter)
+                            {
+                                sb.Append(" " + fi.Logic.ToString().ToUpper() + " ");
+                            }
+                            sb.Append("(");
+                            for (var x = 0; x < fi.Filters.Count; x++)
+                                ParseFilter(fi.Logic, fi.Filters[x], x == fi.Filters.Count - 1);
+                            sb.Append(")");
+                        }
+                        else
+                        {
+                            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 (isend == false && useAllLogic == false)
                 {
                     if (string.IsNullOrEmpty(fi.Field) == false || fi.Filters?.Any() == true)
                     {
@@ -1236,8 +1329,10 @@ bool IsIgnoreFilter(DynamicFilterInfo testFilter)
                     string.IsNullOrEmpty(testFilter.Value?.ToString());
             }
         }
-        static ConcurrentDictionary<MethodInfo, bool> _dicMethodIsDynamicFilterCustomAttribute = new ConcurrentDictionary<MethodInfo, bool>();
-        static bool MethodIsDynamicFilterCustomAttribute(MethodInfo method) => _dicMethodIsDynamicFilterCustomAttribute.GetOrAdd(method, m =>
+
+        private static ConcurrentDictionary<MethodInfo, bool> _dicMethodIsDynamicFilterCustomAttribute = new ConcurrentDictionary<MethodInfo, bool>();
+
+        private static bool MethodIsDynamicFilterCustomAttribute(MethodInfo method) => _dicMethodIsDynamicFilterCustomAttribute.GetOrAdd(method, m =>
         {
             object[] attrs = null;
             try
@@ -1270,6 +1365,7 @@ public TSelect DisableGlobalFilter(params string[] name)
             }
             return this as TSelect;
         }
+
         public TSelect ForUpdate(bool noawait = false)
         {
             if (_transaction == null && _orm.Ado.TransactionCurrentThread != null) this.WithTransaction(_orm.Ado.TransactionCurrentThread);
@@ -1282,29 +1378,35 @@ public TSelect ForUpdate(bool noawait = false)
                 case DataType.CustomMySql:
                     _tosqlAppendContent = $"{_tosqlAppendContent} for update";
                     break;
+
                 case DataType.SqlServer:
                 case DataType.OdbcSqlServer:
                 case DataType.CustomSqlServer:
                     _aliasRule = (_, old) => $"{old} With(UpdLock, RowLock{(noawait ? ", NoWait" : "")})";
                     break;
+
                 case DataType.PostgreSQL:
                 case DataType.OdbcPostgreSQL:
                 case DataType.CustomPostgreSQL:
                 case DataType.KingbaseES:
                     _tosqlAppendContent = $"{_tosqlAppendContent} for update{(noawait ? " nowait" : "")}";
                     break;
+
                 case DataType.Oracle:
                 case DataType.OdbcOracle:
                 case DataType.CustomOracle:
                 case DataType.Dameng:
                     _tosqlAppendContent = $"{_tosqlAppendContent} for update{(noawait ? " nowait" : "")}";
                     break;
+
                 case DataType.Sqlite:
                     break;
+
                 case DataType.GBase:
                 case DataType.ShenTong: //神通测试中发现,不支持 nowait
                     _tosqlAppendContent = $"{_tosqlAppendContent} for update";
                     break;
+
                 case DataType.Firebird:
                     _tosqlAppendContent = $"{_tosqlAppendContent} for update with lock";
                     break;
@@ -1346,6 +1448,7 @@ public bool Any()
             this.Limit(1);
             return this.ToList<int>($"{1}{_commonUtils.FieldAsAlias("as1")}").Sum() > 0; //这里的 Sum 为了分表查询
         }
+
         public long Count()
         {
             var tmpOrderBy = _orderby;
@@ -1370,12 +1473,15 @@ public long Count()
                 _distinct = tmpDistinct;
             }
         }
+
         public TSelect Count(out long count)
         {
             count = this.Count();
             return this as TSelect;
         }
+
         public List<T1> ToList() => ToList(false);
+
         public virtual List<T1> ToList(bool includeNestedMembers)
         {
             if (_diymemexpWithTempQuery != null && _diymemexpWithTempQuery is WithTempQueryParser withTempQueryParser)
@@ -1395,21 +1501,25 @@ public virtual List<T1> ToList(bool includeNestedMembers)
             if (_selectExpression != null) return this.InternalToList<T1>(_selectExpression);
             return this.ToListPrivate(includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevelAll(), null);
         }
+
         public T1 ToOne()
         {
             this.Limit(1);
             return this.ToList().FirstOrDefault();
         }
+
         public T1 First() => this.ToOne();
 
 #if net40
 #else
-        async public Task<bool> AnyAsync(CancellationToken cancellationToken = default)
+
+        public async Task<bool> AnyAsync(CancellationToken cancellationToken = default)
         {
             this.Limit(1);
             return (await this.ToListAsync<int>($"1{_commonUtils.FieldAsAlias("as1")}", cancellationToken)).Sum() > 0; //这里的 Sum 为了分表查询
         }
-        async public Task<long> CountAsync(CancellationToken cancellationToken = default)
+
+        public async Task<long> CountAsync(CancellationToken cancellationToken = default)
         {
             var tmpOrderBy = _orderby;
             var tmpSkip = _skip;
@@ -1433,7 +1543,9 @@ async public Task<long> CountAsync(CancellationToken cancellationToken = default
                 _distinct = tmpDistinct;
             }
         }
+
         public Task<List<T1>> ToListAsync(CancellationToken cancellationToken = default) => ToListAsync(false, cancellationToken);
+
         public virtual Task<List<T1>> ToListAsync(bool includeNestedMembers = false, CancellationToken cancellationToken = default)
         {
             if (_diymemexpWithTempQuery != null && _diymemexpWithTempQuery is WithTempQueryParser withTempQueryParser)
@@ -1453,12 +1565,15 @@ public virtual Task<List<T1>> ToListAsync(bool includeNestedMembers = false, Can
             if (_selectExpression != null) return this.InternalToListAsync<T1>(_selectExpression, cancellationToken);
             return this.ToListPrivateAsync(includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevelAll(), null, cancellationToken);
         }
-        async public Task<T1> ToOneAsync(CancellationToken cancellationToken = default)
+
+        public async Task<T1> ToOneAsync(CancellationToken cancellationToken = default)
         {
             this.Limit(1);
             return (await this.ToListAsync(false, cancellationToken)).FirstOrDefault();
         }
+
         public Task<T1> FirstAsync(CancellationToken cancellationToken = default) => this.ToOneAsync(cancellationToken);
+
 #endif
     }
 }
\ No newline at end of file
diff --git a/FreeSql/Internal/Model/DynamicFilterInfo.cs b/FreeSql/Internal/Model/DynamicFilterInfo.cs
index 6e682207e..1cbb2a345 100644
--- a/FreeSql/Internal/Model/DynamicFilterInfo.cs
+++ b/FreeSql/Internal/Model/DynamicFilterInfo.cs
@@ -16,16 +16,25 @@ namespace FreeSql.Internal.Model
     [Serializable]
     public class DynamicFilterInfo
     {
+        /// <summary>
+        /// 使用所有逻辑运算符,默认为False。
+        /// False:按照原来的模式,只有分组的逻辑运算符会生成到查询条件中,只有OR分组会生成括号。
+        /// True:按照新的模式,所有的逻辑运算符都会生成到查询条件中,所有分组(AND或OR)都会生成括号。
+        /// </summary>
+        public bool UseAllLogic { get; set; }
+
         /// <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>
@@ -35,6 +44,7 @@ public class DynamicFilterInfo
         /// Filters 下的逻辑运算符
         /// </summary>
         public DynamicFilterLogic Logic { get; set; }
+
         /// <summary>
         /// 子过滤条件,它与当前的逻辑关系是 And<para></para>
         /// 注意:当前 Field 可以留空
@@ -42,13 +52,16 @@ public class DynamicFilterInfo
         public List<DynamicFilterInfo> Filters { get; set; }
     }
 
-    public enum DynamicFilterLogic { And, Or }
+    public enum DynamicFilterLogic
+    { And, Or }
+
     public enum DynamicFilterOperator
     {
         /// <summary>
         /// like
         /// </summary>
         Contains,
+
         StartsWith,
         EndsWith,
         NotContains,
@@ -60,16 +73,19 @@ public enum DynamicFilterOperator
         /// Equal/Equals/Eq 效果相同
         /// </summary>
         Equal,
+
         /// <summary>
         /// =<para></para>
         /// Equal/Equals/Eq 效果相同
         /// </summary>
         Equals,
+
         /// <summary>
         /// =<para></para>
         /// Equal/Equals/Eq 效果相同
         /// </summary>
         Eq,
+
         /// <summary>
         /// &lt;&gt;
         /// </summary>
@@ -79,14 +95,17 @@ public enum DynamicFilterOperator
         /// &gt;
         /// </summary>
         GreaterThan,
+
         /// <summary>
         /// &gt;=
         /// </summary>
         GreaterThanOrEqual,
+
         /// <summary>
         /// &lt;
         /// </summary>
         LessThan,
+
         /// <summary>
         /// &lt;=
         /// </summary>
@@ -116,6 +135,7 @@ public enum DynamicFilterOperator
         /// 此时 Value 的值格式为逗号分割:value1,value2,value3... 或者数组
         /// </summary>
         Any,
+
         /// <summary>
         /// not in (1,2,3)<para></para>
         /// 此时 Value 的值格式为逗号分割:value1,value2,value3... 或者数组
@@ -143,5 +163,6 @@ public enum DynamicFilterOperator
     /// 授权 DynamicFilter 支持 Custom 自定义解析
     /// </summary>
     [AttributeUsage(AttributeTargets.Method)]
-    public class DynamicFilterCustomAttribute : Attribute { }
-}
+    public class DynamicFilterCustomAttribute : Attribute
+    { }
+}
\ No newline at end of file