怎样优雅地增删查改(六):按任意字段关键字查询

@

实现

定义按任意字段关键字查询过滤器(IKeywordOrientedFilter)接口,查询实体列表Dto若实现该接口,将筛选指定的目标字段(TargetFields)包含指定的关键字(Keyword)的实体。

public interface IKeywordOrientedFilter {     public string Keyword { get; set; }      public string TargetFields { get; set; } }  

创建应用过滤条件方法:ApplySearchFiltered,代码如下:

protected virtual IQueryable<TEntity> ApplySearchFiltered(IQueryable<TEntity> query, TGetListInput input) {     if (input is IKeywordOrientedFilter)     {         var filteredInput = input as IKeywordOrientedFilter;         if (filteredInput != null)         {             var targetFields = new string[] { "Name", "Title" };             if (!string.IsNullOrEmpty(filteredInput.TargetFields))             {                 targetFields = filteredInput.TargetFields.Split(',');             }              return query.WhereIf(!filteredInput.Keyword.IsNullOrWhiteSpace(),                 FilterByKeywordDynamic<TEntity>(filteredInput.Keyword, targetFields));         }     }     return query; } 

请注意,可应用过滤的条件为:

  1. input需实现IKeywordOrientedFilter接口,且Keyword不为空;
  2. 若filteredInput.TargetFields为空,则默认使用Name和Title字段进行筛选。

对于每一个TargetField,需要在实体中找到对应字段(属性)。若找到,则为此实体字段创建条件筛选的表达式,然后将这些表达式通过Or连接起来,最终返回一个包含多段关键字筛选的Lambda表达式。

创建FilterByKeywordDynamic方法,代码如下:

private Expression<Func<TEntity, bool>> FilterByKeywordDynamic<T>(string keyword, params string[] sortColumns) {     var parameter = Expression.Parameter(typeof(T), "p");     var propertys = sortColumns.Select(sortColumn => typeof(T).GetProperty(sortColumn));      var method = typeof(string)         .GetMethods()         .FirstOrDefault(x => x.Name == "Contains");      var keyConstantExpression = Expression.Constant(keyword, typeof(string));     Expression originalExpression = null;     foreach (var property in propertys)     {         if (property != null)         {             var propertyAccess = Expression.MakeMemberAccess(parameter, property);             var expression = Expression.Call(propertyAccess, method, keyConstantExpression);             if (originalExpression == null)             {                 originalExpression = expression;             }             else             {                 originalExpression = Expression.Or(originalExpression, expression);             }         }     }      var result = originalExpression != null ?             Expression.Lambda<Func<TEntity, bool>>(originalExpression, parameter)             : p => true;     return result;   }  

创建默认的应用过滤规则DefaultConvention,将之前的按组织架构查询和按关键字查询的代码提取到DefaultConvention方法中,此类可派生,使用virtual关键字以便在子类中重写,代码如下:

protected virtual async Task<IQueryable<TEntity>> DefaultConvention(TGetListInput input, IQueryable<TEntity> query) {     query = ApplySearchFiltered(query, input);     query = ApplyUserOrientedFiltered(query, input);     return query; } 

在CreateBriefFilteredQueryAsync和CreateFilteredQueryAsync方法中调用DefaultConvention方法,代码如下:

protected virtual async Task<IQueryable<TEntity>> CreateBriefFilteredQueryAsync(TGetListBriefInput input) {     var query = await ReadOnlyRepository.GetQueryableAsync();      query = await DefaultConvention(input, query);      return query; }    protected override async Task<IQueryable<TEntity>> CreateFilteredQueryAsync(TGetListInput input) {     var query = await ReadOnlyRepository.GetQueryableAsync();      query = await DefaultConvention(input, query);      return query; }   

应用

无需在应用层中更改代码,

在GetAllAlarmInput中实现IKeywordOrientedFilter接口,代码如下:

public class GetAllAlarmInput : PagedAndSortedResultRequestDto,   IKeywordOrientedFilter {     //keyword     public string Keyword { get; set; }     public string TargetFields { get; set; }      ... }  

测试

在告警管理页面建立一些告警

怎样优雅地增删查改(六):按任意字段关键字查询

在筛选中输入关键字“3”,点击查询

怎样优雅地增删查改(六):按任意字段关键字查询

可以看到将筛选出标题包含关键字“3”的告警

怎样优雅地增删查改(六):按任意字段关键字查询

查询的报文Payload如下图:

怎样优雅地增删查改(六):按任意字段关键字查询

发表评论

评论已关闭。

相关文章