【问题标题】:Dynamic SQL Pivot parameters query Entity Framework动态 SQL Pivot 参数查询实体框架
【发布时间】:2020-06-16 07:07:50
【问题描述】:

我有一个查询,当我在 SQL Server Management Studio 中使用它时效果很好。在这里值得一提的是,PIVOT [MedicalInformation.MedicalInformationForm.Name.firstName][MedicalInformation.MedicalInformationForm.Name.lastName] 不是静态的,并且可以变化,也就是它们可以在运行时使用不同的列进行更改

WITH pivot_data AS
(
    SELECT 
        [p].RecordId, -- Grouping Column
        [Key], -- Spreading Column
        [Value] -- Aggregate Column
    FROM 
        [RecordDatas] AS [p]
    INNER JOIN 
        (SELECT [p0].*
         FROM [Records] AS [p0]
         WHERE [p0].[IsDeleted] = 0) AS [t] ON [p].[RecordId] = [t].[ID]
    WHERE
        [p].DatasetId = 1386
        AND [p].[IsDeleted] = 0
        AND ([t].[ProjectID] = 191)
        AND [Key] IN ('MedicalInformation.MedicalInformationForm.Name.firstName', 
                      'MedicalInformation.MedicalInformationForm.Name.lastName')
)
SELECT 
    RecordId, 
    [MedicalInformation.MedicalInformationForm.Name.firstName], 
    [MedicalInformation.MedicalInformationForm.Name.lastName]
FROM 
    pivot_data
PIVOT 
    (MAX([Value]) 
     FOR [Key] IN ([MedicalInformation.MedicalInformationForm.Name.firstName], 
                   [MedicalInformation.MedicalInformationForm.Name.lastName])) AS p

当我尝试从 C# 构建相同的查询动态时会出现问题:

var sql1 = @"
            WITH pivot_data AS
(
SELECT [p].RecordId, -- Grouping Column
[Key], -- Spreading Column
[Value] -- Aggregate Column
FROM [RecordDatas] AS [p]
INNER JOIN (
SELECT [p0].*
FROM [Records] AS [p0]
WHERE [p0].[IsDeleted] = 0
) AS [t] ON [p].[RecordId] = [t].[ID]
where [p].DatasetId = 1386
AND [p].[IsDeleted] = 0
AND ([t].[ProjectID] = 191)
AND  [Key] IN( {0} , {1}))
SELECT RecordId, {2},{3}
FROM pivot_data
PIVOT (max([Value]) FOR [Key] IN ({2},{3})) AS p;";

await repositoryMapper.Repository.Context.Database.ExecuteSqlCommandAsync(sql1, 
"MedicalInformation.MedicalInformationForm.Name.firstName", 
"MedicalInformation.MedicalInformationForm.Name.lastName", 
"[MedicalInformation.MedicalInformationForm.Name.firstName]", 
"[MedicalInformation.MedicalInformationForm.Name.lastName]");

我的问题来了 - 当使用 ExecuteSqlCommandAsync 生成查询并为 PIVOT 列([MedicalInformation.MedicalInformationForm.Name.firstName][MedicalInformation.MedicalInformationForm.Name.lastName])添加参数时,语法有问题。我收到一个错误:

“@p2”附近的语法不正确。

我试图获取 Entity Framework 正在执行的生成查询,它看起来像这样:

exec sp_executesql N'
            WITH pivot_data AS
(
SELECT [p].RecordId, -- Grouping Column
[Key], -- Spreading Column
[Value] -- Aggregate Column
FROM [RecordDatas] AS [p]
INNER JOIN (
SELECT [p0].*
FROM [Records] AS [p0]
WHERE [p0].[IsDeleted] = 0
) AS [t] ON [p].[RecordId] = [t].[ID]
where [p].DatasetId = 1386
AND [p].[IsDeleted] = 0
AND ([t].[ProjectID] = 191)
AND  [Key] IN( @p0 , @p1))
SELECT RecordId, @p2,@p3
FROM pivot_data
PIVOT (max([Value]) FOR [Key] IN (@p2,@p3)) AS p;
',N'@p0 nvarchar(4000),
@p1 nvarchar(4000),
@p2 nvarchar(4000),
@p3 nvarchar(4000)',
@p0=N'MedicalInformation.MedicalInformationForm.Name.firstName',
@p1=N'MedicalInfo rmation.MedicalInformationForm.Name.lastName',
@p2=N'[MedicalInformation.MedicalInformationForm.Name.firstName]',
@p3=N'[MedicalInformation.MedicalInformationForm.Name.lastName]'

请帮帮我,我不确定这里有什么问题

【问题讨论】:

    标签: c# sql-server entity-framework .net-core entity-framework-core


    【解决方案1】:

    问题是这样的一行:

    选择 RecordId,@p2,@p3

    无效。语句是预编译的,您不能更改参数中的字段名称 - 语句的字段名称是静态的。

    您必须进入 EntityFramework 不支持的动态 SQL(在允许您提交任何您想要的 SQL 的函数之外)。基本上,您必须以不使用参数为字段名称的方式创建有效语句。

    这并不意味着您不能使用占位符并且 - 在 C# 中 - 对字符串运行替换操作,但这意味着当您将更改的脚本提交到数据库时必须完成替换。

    SQL Server 的限制。

    【讨论】:

      【解决方案2】:

      您不能从参数中为SELECT RecordId, @p2,@p3 中的@p2@p3 赋值。您需要在运行查询之前设置这些语句,如下所示:

      var sql1 = @"
                  WITH pivot_data AS
      (
      SELECT [p].RecordId, -- Grouping Column
      [Key], -- Spreading Column
      [Value] -- Aggregate Column
      FROM [RecordDatas] AS [p]
      INNER JOIN (
      SELECT [p0].*
      FROM [Records] AS [p0]
      WHERE [p0].[IsDeleted] = 0
      ) AS [t] ON [p].[RecordId] = [t].[ID]
      where [p].DatasetId = 1386
      AND [p].[IsDeleted] = 0
      AND ([t].[ProjectID] = 191)
      AND  [Key] IN( {0} , {1}))
      SELECT RecordId, [MedicalInformation.MedicalInformationForm.Name.lastName],[MedicalInformation.MedicalInformationForm.Name.lastName]
      FROM pivot_data
      PIVOT (max([Value]) FOR [Key] IN ({2},{3})) AS p;";
      
      await repositoryMapper.Repository.Context.Database.ExecuteSqlCommandAsync(sql1, 
      "MedicalInformation.MedicalInformationForm.Name.firstName", 
      "MedicalInformation.MedicalInformationForm.Name.lastName", 
      "[MedicalInformation.MedicalInformationForm.Name.firstName]", 
      "[MedicalInformation.MedicalInformationForm.Name.lastName]");
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-16
        • 1970-01-01
        • 1970-01-01
        • 2012-05-11
        相关资源
        最近更新 更多