代码之家  ›  专栏  ›  技术社区  ›  Fabricio Rodriguez

在dbcontext上构建过滤器

  •  0
  • Fabricio Rodriguez  · 技术社区  · 7 年前

    我有一个asp.net core 2.1web api。我想知道是否有一个“优雅的解决方案”可以基于查询字符串在我的dbcontext上构造过滤器?所以…假设我有一个[可选]查询字符串:

        // GET: api/Accounts
        [HttpGet]
        public IEnumerable<File> GetAccount([FromQuery] bool? isActive)
        {
            if (isActive.HasValue)
                return _context.Accounts.Where(a => a.IsActive == isActive.Value);
            else
                return _context.Accounts;
        }
    

    很简单…但是假设我有许多(可选)查询字符串:

        // GET: api/Accounts
        [HttpGet]
        public IEnumerable<File> GetAccount([FromQuery] bool? isActive, [FromQuery] string type, [FromQuery] int? agentId, [FromQuery] bool? someOtherFilter)
        {
    
        }
    

    正如您所看到的,构建过滤器现在变得更加困难,因为可以有过滤器的组合,这取决于提供了哪些过滤器。我可以检查第一个查询字符串是否有值,如果有,则执行筛选并将结果保存到临时变量中。然后我可以检查下一个查询字符串,如果它有一个值,然后对临时变量执行该过滤器,依此类推。但听起来会很慢…还有其他建议吗?谢谢。。。

    2 回复  |  直到 7 年前
        1
  •  2
  •   SᴇM    7 年前

    您可以使用 if/else :

    [HttpGet]
    public IEnumerable<File> GetAccount([FromQuery] bool? isActive, [FromQuery] string type, [FromQuery] int? agentId, [FromQuery] bool? someOtherFilter)
    {
        var accounts = context.Accounts;
        if(isActive.HasValue) 
            accounts.Where(a => a.IsActive == isActive.Value);
    
        if(!string.IsNullOrEmpty(type)) 
            accounts.Where(a => a.Type == type);
    
        if(agentId.HasValue) 
            accounts.Where(a => a.AgentId == agentId.Value);
    
        . . .
    
        if(someOtherFilter.HasValue) 
            accounts.Where(a => a.SomeOtherFilter == someOtherFilter.Value);
    }
    

    或者在linq to sql中可以检查 null 在你的内心 Where() 方法:

    public IEnumerable<File> GetAccount([FromQuery] bool? isActive, [FromQuery] string type, [FromQuery] int? agentId, [FromQuery] bool? someOtherFilter) =>
        context.Accounts.Where(a => 
            (!isActive.HasValue || a.IsActive == isActive.Value) && 
            (string.IsNullOrEmpty(type) || a.Type == type)       &&
            (!agentId.HasValue || a.AgentId== agentId.Value)     &&
            . . .
            (!someOtherFilter.HasValue || a.SomeOtherFilter== someOtherFilter.Value);
    
        2
  •  2
  •   momo    7 年前

    我建议添加一个扩展来隐藏所有的脏工作,并创建如下内容:

    public class AccountQuery
    {
        public bool IsActive { get; set; }
        public int? AgentId { get; set; }
        ...
    }
    
    public static class Extensions
    {
        public static IQueryable<Account> ApplyFilter(this IQueryable<Account> query, AccountQuery queryObj)
        {
            if (queryObj.IsActive)
                query = query.Where(...);
    
            if (queryObj.AgentId.HasValue)
                query = query.Where(...);
    
            // some other filters
            return query;
        }
    }
    
    [HttpGet]
    public IEnumerable<File> GetAccount([FromQuery] AccountQuery queryObj) 
    {
        var query = _context.Accounts.AsQueryable();
        query = query.ApplyFilter(queryObj);
        ...
    }