Построение фильтров на DbContext - PullRequest
0 голосов
/ 08 июня 2018

У меня есть 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 голосов
/ 08 июня 2018

Я бы предложил добавить расширение, чтобы скрыть всю грязную работу и создать что-то вроде этого:

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);
    ...
}
0 голосов
/ 08 июня 2018

Вы можете проверить все дополнительные значения с помощью 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);
...