查询过滤器

介绍

全局过滤器的作用是设置 一个查询条件 ,当你查询操作的时候满足这个条件,那么你的查询就会附加你设置的条件

应用场景:过滤假删除数据 比如 每个查询后面都要加 isdelete=false

1、表过滤器 (推荐

 1.1 手动添加过滤器

根据实体添加过滤器,只要是这个实体的Queryable操作都会生效

/***过滤器写的位置***/
SqlSugarClient Db= new SqlSugarClient(new ConnectionConfig(){
           ConnectionString = "连接符字串", 
           DbType = DbType.SqlServer,
           IsAutoCloseConnection = true},
           db=>{
                  
               //过滤器写在这儿就行了
               db.QueryFilter.AddTableFilter<IDeleted>(it => it.IsDeleted==false);
               //如果是多租户
               //db.GetConnection(XXX).AddTableFilter 
               //用GetConnection还是GetConnectionScope和你代码要保持一致
           });
           
           
           
/***具体用例***/           

db.QueryFilter.AddTableFilter<Order>(it => it.Name.Contains("a"));
db.QueryFilter.AddTableFilterIF<Order>( isAdmin == false ,it => it.Name.Contains("a"));


//接口过滤器 (继承接口的类都有效) 请升级 5.1.3.47
db.QueryFilter.AddTableFilter<IDeleted>(it => it.IsDelete==false);

  
/****用例讲解***/
db.QueryFilter.AddTableFilter<Order>(it => it.Name.Contains("a"));//给Order类型加一个过滤器

//单表有效
db.Queryable<Order>().ToList();
// SELECT [Id],[Name],[Price],[CreateTime],[CustomId] FROM [Order]  WHERE  ([Name] like '%'+@MethodConst0+'%') 

//多表查询也有效
db.Queryable<OrderItem>().LeftJoin<Order>((i, o) => i.OrderId == o.Id)
        .Select((i,o)=>i).ToList();
//SELECT i.* FROM [OrderDetail] i Left Join [Order]  o  
//ON ( [i].[OrderId] = [o].[Id] )  AND  ([o].[Name] like '%'+@MethodConst1+'%')

 1.2 禁用、清空、备份和还原 

请升级5.1.3.47及以上版本

db.QueryFilter
.AddTableFilter<IDeletedFilter>(it => it.IsDeleted==false)//IDeletedFilter是自定义接口,继承这个接口的实体有效
.AddTableFilterIF<ITenantFilter>(isAdmint==false,it=>it.OrgId==用户OrgId);//ITenantFilter自定义接口

//用例1:单条语句清空,只影响当前语句
db.Queryable<Order>().ClearFilter().ToList();//所有过滤器都无效
db.Queryable<Order>().ClearFilter<IDeletedFilter>().ToList();//只有IDeletedFilter过滤器无效
db.Queryable<Order>().ClearFilter<IDeletedFilter,ITenantFilter>().ToList();//IDeletedFilter+ITenantFilter无效
  
//用例2:当前上下文清空 ,不会影响其他请求,只是当前请求清空
db.QueryFilter.Clear();
db.QueryFilter.Clear<IDeletedFilter>(); 

//用例3:清空并还原 ,不会影响其他请求,只是当前请求清空
db.QueryFilter.ClearAndBackup();//有多个重载 ClearAndBackup<T,T2>();
db.Queryable<Order>().ToList();
db.QueryFilter.Restore();//还原过滤器 (适合下面代码还需要过滤器情况)

 1.3 联表查询设置

//追加在on后面
db.QueryFilter.AddTableFilter<Order>(it=>it.Id==1)
//追加在where后面
db.QueryFilter.AddTableFilter<Order>(it=>it.Id==1,QueryFilterProvider.FilterJoinPosition.Where)

 1.4 动态添加 

 1.3.1 继承接口全局添加

//需要升级到 5.1.3.46-preview10 
db.QueryFilter.AddTableFilter<IDeleted>(it => it.IsDelete==false);
//符合条件执行过滤器
db.QueryFilter.AddTableFilterIF<IDeleted>(IsFilter==true ,it => it.IsDelete==false);

//实体类继承该接口就有效
public interface IDeleted
{
   public bool IsDelete{get;set;}
}

1.3.2 动态过滤器( 接口和类都可以)   5.1.4.106-preview13+

//程序启动时注册 (需要安装Dynamic.Core组件)
StaticConfig.DynamicExpressionParserType = typeof(DynamicExpressionParser);

 //注意:第二个参数必须要有$
 //参数化:可以缓存创建性能好
 //如果没有$ 需要用 FormattableStringFactory.Create("it=>it.Id=={0}", 1)  

//调用如下 (Type可以是接口 也可以是类)
db.QueryFilter
.AddTableFilter(typeof(IUser), "it", $"it=>it.UserName={ "jack" } ")//一定要用$"{}"方式给参数赋值
.AddTableFilter(typeof(IOrg), "it", $" it=> it.OrgId={1} || it.OrgId={2}  ");//一定要用$"{}"方式给参数赋值

//常用的C#方法都可以用 如Contains、时间.Date、时间.ToString("yyyy-MM-dd")  
//如果要用SqlFunc方法:
//https://www.donet5.com/Home/Doc?typeId=2569

2、修改和删除用过滤器

查询是配置就生效,更新和删除要分自动和手动2种模式

2.1 局部设置

//删除
 db.Deleteable<Order>().EnableQueryFilter()//启用过滤器
 .Where(it => it.Id == 0)
 .ExecuteCommand();//支持全局设置2.1
 
//表达式方式更新
  db.Updateable<Order>().EnableQueryFilter()//启用过滤器
  .SetColumns(it => it.Name == "a")
  .Where(it => it.Id == 1)
  .ExecuteCommand();//支持全局设置 2.1
  
//对象方式更新 5.1.4.106-preview09++ 
db.Updateable(updateObj)
.PageSize(1)//需要一条一条更新才能用过滤器
.EnableQueryFilter().ExecuteCommand()//不支持全局设置需要手动处理

2.2 全局设置 (5.1.4.62)

 DbType = DbType.SqlServer,
 ConnectionString = Config.ConnectionString,
 IsAutoCloseConnection = true,
 MoreSettings=new ConnMoreSettings 
 { 
      IsAutoDeleteQueryFilter=true,//启用删除查询过滤器  
      IsAutoUpdateQueryFilter=true//启用更新查询过滤器 (表达式更新,如果是实体方式更新建议先查询在更新)
 }
 
 //清空过滤器 当前上下文有限 (全局设置可以这样清空)
 db.QueryFilter.Clear();
 db.Deleteable<Order>().Where(it => it.Id == 0).ExecuteCommand();

3、子查询用过滤器

SqlFunc.Subqueryable<Order>().EnableTableFilter().Where(s=>s.id==it.xx).Any()

4、联表过滤器位置配置

On是加到On后面 (默认符合多数情况

 db.QueryFilter.AddTableFilter<Order>(it => it.Id == 1, QueryFilterProvider.FilterJoinPosition.On);

Where是加到Where后面 (LeftJoin需要根据从表强制过滤主表才用

 db.QueryFilter.AddTableFilter<Order>(it => it.Id == 1, QueryFilterProvider.FilterJoinPosition.Where);

5、 不依赖实体过滤器

唯一优点不依赖实体,使用了过滤器所有 Queryable的 sql都会加上这一句

 //表单Queryable查询
 db2.QueryFilter.Add(new SqlFilterItem()
            {
                FilterValue = it =>
                {
                    //Writable logic
                    return new SqlFilterResult() { Sql = " name like '%a%' " };
                },
                IsJoinQuery = false // 单表生效  
            });
 //多表Queryable查询           
 db2.QueryFilter.Add(new SqlFilterItem()
            {
                FilterValue = it =>
                {
                    //Writable logic
                    return new SqlFilterResult() { Sql = " o.name like '%a%' " };
                },
                IsJoinQuery = true //多表生效
 });
 
 //可以用清空所有来清空

6、老版本写法

表过滤器老版本写法

//老版本
//db.QueryFilter.Add(new TableFilterItem<Order>(it => it.Name.Contains("a"),true))//true表示Leftjoin加on后面

//技巧:表过滤器使用Sql语句
//db.QueryFilter.AddTableFilter(it => SqlFunc.MappingColumn(default(bool),"id=1");

//清除过滤器
//db.Queryable<Order>().Filter(null,true).ToList();7、

7、导航过滤器疑问

针对一对一并且是单主键关联进行了优化(只优化了一对一并且是单主键

因为主键是唯一的所以根本就不需要过滤器

目前所有用户都满足这个优化条件

如果你有新的疑虑可以看下面讨论

https://www.donet5.com/Ask/9/27289

8、相关功能

当前是介绍查询条件过滤,如果你想用AOP等功能可以看

https://www.donet5.com/Home/Doc?typeId=1204



关闭
果糖网