在DbContext

时间:2018-06-08 09:08:49

标签: linq entity-framework-core query-string asp.net-core-webapi

我有一个ASP .Net Core 2.1 Web 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)
    {

    }

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

2 个答案:

答案 0 :(得分:2)

您可以使用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);

答案 1 :(得分:2)

我建议添加一个扩展来隐藏所有脏工作并创建这样的东西:

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);
    ...
}