【问题标题】:How to stop ExecuteSqlInterpolated from wrapping string params with single quotes?如何阻止 ExecuteSqlInterpolated 用单引号包装字符串参数?
【发布时间】:2021-10-14 23:12:17
【问题描述】:

我在 EF Core 3 中调用了具有多个字符串参数的 ProgresSQL 服务器。其中之一是一个字符串,它是已经用单引号包裹的字符串的串联,如下所示:

var listOfParams = "'a',','b','c'";

然后传递给如下所示的查询:

var id = "Customer1";
DbContext.Database.ExecuteSqlInterpolated(
   "SELECT ""CustomerNumber"" FROM dbo.""Customer"" 
      WHERE ""Id"" = {id} AND ""CustomerNumber"" IN ({listOfParams})");

问题是,虽然用引号包裹 id 是正确的,但对于已经有引号的第二个参数,会发生某种形式的第二次换行,或者可能会转义单引号,这是我想避免的。 然而,我找不到任何相对简单的方法。如果可以将 listOfParams 保留为 SQL 参数,那就完美了,否则查询计划的缓存将是不可能的。直接传递列表似乎也不起作用。看起来 EF Core 不支持它。

谢谢,拉德克

【问题讨论】:

  • 用引号括起来绝对不正确,ExecuteSqlInterpolated 也不是这样做的。它找到插值并将其更改为命名参数,这意味着您最终得到""CustomerNumber"" IN (@listOfParams),它与""CustomerNumber"" = @listOfParams 相同,并且该参数只是一个恰好包含逗号的字符串,它永远不会被解释为一个列表。您需要在变量上使用 JSON 参数或 STRING_SPLIT 或类似参数
  • @Charlieface:其实你的回答给了我一个想法。我可以稍微修改查询以包含以下内容: select unnest(string_to_array({listOfParams}, ',')) as "CustomerNumber" 然后在我拥有的所有查询中使用此选择的结果。实际上我已经检查过了,它似乎正在工作。谢谢:)
  • 确实是一种方法,但是您需要删除引号并像这样""CustomerNumber"" IN (select * from unnest(string_to_array({listOfParams}, ',')))

标签: c# postgresql .net-core npgsql ef-core-3.0


【解决方案1】:

您是否尝试过仅使用 LINQ 方法?

var listOfParams =  "a b c".Split();
var r = DBContext.Customer
  .Where(c => c.Id == id && listOfParams.Contains(c.CustomerNumber))
  .Select(c => c.CustomerNumber);

在 SQLServer 中,.Contains 被映射到 IN - PG 很可能是相同的

【讨论】:

  • 好吧,实际的查询相当复杂,不幸的是阻止了 Linq 的使用。
  • 您应该发布实际查询,以便我们可以提供帮助 - 如果您不能将任何简化的答案反向转换回复杂的变体,那么发布简化的问题是没有意义的。现在可以将 n 匹配的复杂 SQL 与 LINQ 混合使用
  • 我明白你的意思。让我尝试一下 Charlieface 以某种方式提出的一种解决方案,如果我再次卡住,我将提供完整的查询(当然有点混淆)。
【解决方案2】:

如果您正在寻找参数化您的列表 (a, b, c),那么您可能想要传递一个数组参数 - 这应该得到 Npgsql 和 EF Core 提供程序的完全支持,并正确重用查询计划/准备好的语句。

请注意,对于数组,您需要使用 PG 的 = ANY (<array>) 构造而不是 IN。

var id = "Customer1";
var listOfParams = new[] { "a", "b", "c" };

DbContext.Database.ExecuteSqlInterpolated(
   "SELECT ""CustomerNumber"" FROM dbo.""Customer"" 
      WHERE ""Id"" = {id} AND ""CustomerNumber"" = ANY ({listOfParams})");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-25
    相关资源
    最近更新 更多