我正在研究 .Net 核心 API,并且有一个分页端点,可以采用可选的查询参数。例如,端点列出项目,您还可以指定过滤包含或等于特定值的字段。
https://endpoint/items?pageparams=pageData&field1Contains=value&field1Equals=value&field2Contains=value&field2Equals=value
[HttpGet]
[Authorize(AuthenticationSchemes = AuthSchemes)]
[Route("items")]
public async Task<IActionResult> GetPagedItems(
[FromQuery] PageParameters pageParameters,
[FromQuery] OptionalSearchParams searchParameters)
{
// logic
}
目前我将包含视为高于等于的高阶,因此如果您为同一字段同时传递 'equals' 和 'contains',将应用 'contains' 而忽略 'equals'。
API 还动态构建查询和 where 子句,出于明显的安全原因,我真的不想这样做。
var searchClauses = new List<string>();
if (!string.IsNullOrEmpty(searchParameters.Field1Contains))
{
searchClauses.Add($" ([Field1] LIKE '%{searchParameters.Field1Contains}%')");
}
else if (!string.IsNullOrEmpty(searchParameters.Field1Equals))
{
searchClauses.Add($" ([Field1] = '{searchParameters.Field1Equals}') ");
}
// logic to read other optional params and add where clauses to list
var query = @$"SELECT TOP {pageParameters.PageSize}
-- statement removed for brevity --
FROM [SomeTable]
ORDER BY [Field]
OFFSET {((pageParameters.PageNumber - 1) * pageParameters.PageSize)} ROW)
BASE
WHERE {string.Join(" AND ", searchClauses)}
我遇到的问题是我不知道如何将这些值作为参数/存储过程传递给数据库,因为它们不会总是被使用,并且有基于优先级应用的逻辑。不完全正确...我确实设法构建了一个 SQL 查询,但它很庞大,并且在 where 子句中有太多嵌套的 case/select 语句,这将是维护/性能影响的噩梦。
是否有更好的方法来处理可选字段过滤器,同时以参数化方式进行分页?我真的不想从数据库中获取每个项目然后过滤,因为有可能返回数千个项目。
答案 0 :(得分:0)
Vladimir 指定的阅读为我指明了最佳方向,特别是由过程本身生成然后执行的动态 sql。见http://www.sommarskog.se/dyn-search.html#paramquery