【问题标题】:Handling optional query params in API and Database处理 API 和数据库中的可选查询参数
【发布时间】:2021-01-11 05:47:41
【问题描述】:

我正在开发一个 .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
}

目前我将 contains 视为比 equals 高阶,因此如果您为同一字段同时传递 '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 语句,这将是维护/性能影响的噩梦。

是否有更好的方法来处理可选字段过滤器,同时以参数化方式进行分页?我真的不想从数据库中获取所有项目然后进行过滤,因为可能会返回数千个项目。

【问题讨论】:

  • 你的 c# 代码应该有一个所有参数和类型(int、varchar、...)的列表。然后根据用户选择的参数,您可以从列表中选择项目。为了更通用,您可以使用 GetSchema 方法,该方法将从 SQL 数据库中获取表、列、类型。
  • 不是我想要的,是的,所有字段和类型都知道,但我无法选择传递存储过程的参数,它们是具体的。我还需要根据 contains/equals 要求进行更改。
  • sql server 中的输入参数可以为空。因此,在存储过程中,您可以测试输入参数是否为 null,并设置为默认值或忽略。
  • @MattSykes,必读:Dynamic Search Conditions in T‑SQL,作者 Erland Sommarskog。我个人在我的系统中经常使用带有 OPTION (RECOMPILE) 的静态 SQL。

标签: c# sql asp.net-core


【解决方案1】:

Vladimir 指定的阅读为我指明了最佳方向,特别是由过程本身生成然后执行的动态 sql。见http://www.sommarskog.se/dyn-search.html#paramquery

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-10
    • 2011-04-08
    • 2012-03-28
    • 1970-01-01
    • 2018-03-27
    • 1970-01-01
    • 1970-01-01
    • 2016-09-19
    相关资源
    最近更新 更多