在 DbContext 上构建过滤器
Building filters on DbContext
我有一个 ASP .Net Core 2.1 Web Api。我想知道是否有 "elegant solution" 用于根据查询字符串在我的 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)
{
}
如您所见,构建过滤器现在变得更加困难,因为可以存在过滤器的组合,具体取决于提供的过滤器。我可以检查第一个查询字符串是否有值,如果有,则执行过滤器并将结果保存到临时变量中。然后我可以检查下一个查询字符串,如果它有值,然后对临时变量执行该过滤器,依此类推。但这听起来会很慢......还有其他建议吗?谢谢...
您可以使用 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);
}
或者在 sql 的 linq 中,您可以在 Where()
方法中检查 null
:
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);
我建议添加一个扩展来隐藏所有肮脏的工作并创建这样的东西:
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);
...
}
我有一个 ASP .Net Core 2.1 Web Api。我想知道是否有 "elegant solution" 用于根据查询字符串在我的 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)
{
}
如您所见,构建过滤器现在变得更加困难,因为可以存在过滤器的组合,具体取决于提供的过滤器。我可以检查第一个查询字符串是否有值,如果有,则执行过滤器并将结果保存到临时变量中。然后我可以检查下一个查询字符串,如果它有值,然后对临时变量执行该过滤器,依此类推。但这听起来会很慢......还有其他建议吗?谢谢...
您可以使用 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);
}
或者在 sql 的 linq 中,您可以在 Where()
方法中检查 null
:
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);
我建议添加一个扩展来隐藏所有肮脏的工作并创建这样的东西:
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);
...
}