sqlsugar表过滤filter探究

发布时间 2023-12-22 00:37:40作者: 果小天

sqlsugar支持表过滤器,如果表里面有这个字段,则可以自动添加sql语句过滤
但是有一些疑问,就是如果表没有这个字段会自动添加么,肯定是不会,但是有时候脑袋就是钻牛角尖,总感觉会加语句,所以找了点时间看了下源码。
试图搞清楚里面的逻辑

所以如何是如何添加过滤字段的呢,有较多的方式添加,许多框架基本都是这种用法,例如 admin.net 中的代码



SqlSugarScope sqlSugar = new(dbOptions.ConnectionConfigs.Adapt<List<ConnectionConfig>>(), db =>
 {
        dbOptions.ConnectionConfigs.ForEach(config =>
         {
           var dbProvider = db.GetConnectionScope(config.ConfigId);
           SetDbAop(dbProvider, dbOptions.EnableConsoleSql);
           SetDbDiffLog(dbProvider, config);
           });
});

其中SetDbAop 设置db过滤 其中代码 :


 // 配置租户过滤器
 var tenantId = App.User?.FindFirst(ClaimConst.TenantId)?.Value;
 if (!string.IsNullOrWhiteSpace(tenantId))
     db.QueryFilter.AddTableFilter<ITenantIdFilter>(u => u.TenantId == long.Parse(tenantId));

添加租户字段过滤 ,多租户必备字段,让我们在业务中无需考虑隔离问题。但是这个东西是如何运行的还是需要研究一下。
于是顺藤摸瓜,沿着方法一路找就好了,但是前提是我们下载了sqlsugar的源码,好在它也是开源的,直接下载源码即可
可以看到 AddTableFilter=>调用了Add(filter);


 public QueryFilterProvider AddTableFilter<T>(Expression<Func<T, bool>> expression, FilterJoinPosition filterJoinType = FilterJoinPosition.On)
 {
     bool isJoinOn = filterJoinType == FilterJoinPosition.On;
     TableFilterItem<T> filter = new TableFilterItem<T>(expression, isJoinOn);
     Add(filter);
     return this;
 }
public IFilter Add(SqlFilterItem filter)
 {
     if (_Filters == null)
     {
         _Filters = new List<SqlFilterItem>();
     }

     _Filters.Add(filter);
     return this;
 }
private List<SqlFilterItem> _Filters { get; set; }

其将 过滤注入了 _Filters
_Filters是私有的,肯定有向外展示的字段 ,为GeFilterList


 public List<SqlFilterItem> GeFilterList
 {
     get
     {
         if (_Filters == null)
             _Filters = new List<SqlFilterItem>();
         return _Filters;
     }
 }

直接查看该字段的引用 九个
不多,慢慢找就找到了 ,加上我们的注释


 public string GetValue(Expression expression)
 {
     var result = "";
     if (this.Context.SugarContext != null)
     {
         var db = this.Context.SugarContext.Context;
         BindingFlags flag = BindingFlags.Instance | BindingFlags.NonPublic;
	//当前表类型
         Type type = this.Context.SubTableType;
         var isWhere = HasWhere;
         if (db.QueryFilter.GeFilterList != null) {
             foreach (var item in db.QueryFilter.GeFilterList)
             {
                 PropertyInfo field = item.GetType().GetProperty("exp", flag);
                 if (field != null)
                 {
	   // 加入的过滤接口
                     Type ChildType = item.GetType().GetProperty("type", flag).GetValue(item, null) as Type;
		//如果表实现了该接口,则加入过滤
                     if (ChildType == type|| (ChildType.IsInterface&&type.GetInterfaces().Contains(ChildType)))
                     {
                         var entityInfo = db.EntityMaintenance.GetEntityInfo(ChildType);
                         var exp = field.GetValue(item, null) as Expression;
                         var whereStr = isWhere ? " AND " : " WHERE ";
                         isWhere = true;
                         result += (whereStr + SubTools.GetMethodValue(Context, exp, ResolveExpressType.WhereSingle));
                     }
                 }
             }
         }
     }
     return result;
 }

所以 我们研究了一下,如何进行表字段过滤,顺便解决了一下心中疑惑,同时是不是自己也可以造轮子了呢。:)

总结 :实现了该过滤接口的表才会进行过滤,没有则不会。至于是如何实现可以看上面代码。