Dynami c SQL Запрос параметров Pivot Entity Framework - PullRequest
0 голосов
/ 03 марта 2020

У меня есть запрос, который отлично работает, когда я использовал его в SQL Server Management Studio. Здесь стоит упомянуть, что PIVOT [MedicalInformation.MedicalInformationForm.Name.firstName] и [MedicalInformation.MedicalInformationForm.Name.lastName] НЕ являются стати c и могут различаться или могут изменяться во время выполнения с разными столбцами

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 из 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]'

Пожалуйста, помогите мне, я не уверен, что здесь проблема

Ответы [ 2 ]

1 голос
/ 04 марта 2020

Проблема в том, что такая строка:

SELECT RecordId, @ p2,@p3

недопустима. Выражения предварительно скомпилированы, и вы не можете изменять имена полей в параметрах - имена полей для оператора следующие: c.

Вы должны go в Dynami c SQL, который EntityFramework не поддерживает (вне функций, позволяющих вам отправлять все, что вы хотите * 1017). По сути, вы должны создать действительный оператор таким образом, чтобы НЕ использовать параметры, являющиеся именами полей.

Это НЕ означает, что вы не можете использовать заполнители и - в C# - запустить операцию замены строки, но это означает, что замена должна быть завершена, когда вы ТОГДА отправляете измененный скрипт в базу данных.

Ограничение SQL Сервер.

1 голос
/ 04 марта 2020

Нельзя назначить значения этих @p2, @p3 в SELECT RecordId, @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]");
...