sql server-SqlCommand在尝试使用c#执行查询时返回错误
本文关键字:查询 执行 返回 错误 server-SqlCommand sql | 更新日期: 2023-09-27 17:59:03
我正在开发一个项目,该项目将允许用户仅通过选择列来构建查询。
我的应用程序似乎运行良好,并生成了正确的查询。但是当我执行查询时,我得到以下异常
"Tasks.Duration"列在选择列表中无效,因为它是不包含在聚合函数或GROUP BY子句中。
从这里开始,我的查询实际上包括正确的GROUP BY
语句
以下是我的应用程序生成的查询
SELECT
[Campaign].[Title] AS [CampaignTitle]
,CASE WHEN [Task].[Duration] <= @p0 THEN @p1 WHEN [Task].[Duration] >= @p2 AND [Task].[Duration] <= @p3 THEN @p4 ELSE @p5 END AS [9pl1WbY1ZkSvSpel3g4xmw]
,COUNT(1) AS [Ib7ZS4arHkSUWhf4saEtmg]
,SUM(CASE WHEN [Task].[Duration] <= @p6 THEN @p7 ELSE @p8 END) AS [xW1GmttC6kWHsc9QIEPN9w]
FROM [Tasks] AS [Task]
INNER JOIN [Campaigns] AS [Campaign] ON [Campaign].[Id] = [Task].[CampaignId]
INNER JOIN [Users] AS [User] ON [User].[Id] = [Task].[CompletedBy]
INNER JOIN [Results] AS [Result] ON [Result].[Id] = [Task].[ResultId]
WHERE
[Result].[IsCompleted] = @p9 AND ( [User].[LastName] = @p10 OR [User].[LastName] = @p11 )
GROUP BY
[Campaign].[Title]
,CASE WHEN [Task].[Duration] <= @p13 THEN @p14 WHEN [Task].[Duration] >= @p15 AND [Task].[Duration] <= @p16 THEN @p17 ELSE @p18 END
HAVING
COUNT(1) >= @p12
ORDER BY
[Campaign].[Title]
,CASE WHEN [Task].[Duration] <= @p19 THEN @p20 WHEN [Task].[Duration] >= @p21 AND [Task].[Duration] <= @p22 THEN @p23 ELSE @p24 END
更好的是,我尝试用参数值手动替换参数名称。然后我接受了他们的输出查询,并在SSMS中执行了它,它工作起来没有问题。
这就是我执行查询的方式
using (SqlConnection connection = new SqlConnection(this.connectionString))
using (SqlDataAdapter sqlAdapter = new SqlDataAdapter(selectCommand))
{
try
{
selectCommand.Connection = connection;
DataTable table = new DataTable();
sqlAdapter.Fill(table);
return table;
}
catch (Exception e)
{
throw new ReportException(string.Format("{0} {1}", e.Message, e.GetType().FullName));
}
}
这是我用来用值替换参数的方法
private string GetPlainQuery(SqlCommand selectCommand)
{
string output = selectCommand.CommandText;
for (int i = selectCommand.Parameters.Count - 1; i >= 0; i--)
{
var p = selectCommand.Parameters[i];
string value = p.Value.ToString();
if (p.SqlDbType == SqlDbType.NChar || p.SqlDbType == SqlDbType.NText || p.SqlDbType == SqlDbType.NVarChar || p.SqlDbType == SqlDbType.Text || p.SqlDbType == SqlDbType.Char || p.SqlDbType == SqlDbType.Date || p.SqlDbType == SqlDbType.DateTime || p.SqlDbType == SqlDbType.SmallDateTime)
{
value = string.Format("'{0}'", value.Replace("'", "''"));
}
output = output.Replace(p.ParameterName, value);
}
return output;
}
导致此错误的原因是什么?我该怎么修?
更新
这是我用值替换参数后的查询
SELECT
[Campaign].[Title] AS [CampaignTitle]
,CASE WHEN [Task].[Duration] <= 100 THEN '<100' WHEN [Task].[Duration] >= 100 AND [Task].[Duration] <= 200 THEN 'BETWEEN 100 AND 200' ELSE '>200' END AS [9pl1WbY1ZkSvSpel3g4xmw]
,COUNT(1) AS [Ib7ZS4arHkSUWhf4saEtmg]
,SUM(CASE WHEN [Task].[Duration] <= 100 THEN 1 ELSE 0 END) AS [xW1GmttC6kWHsc9QIEPN9w]
FROM [Tasks] AS [Task]
INNER JOIN [Campaigns] AS [Campaign] ON [Campaign].[Id] = [Task].[CampaignId]
INNER JOIN [Users] AS [User] ON [User].[Id] = [Task].[CompletedBy]
INNER JOIN [Results] AS [Result] ON [Result].[Id] = [Task].[ResultId]
WHERE
[Result].[IsCompleted] = 1 AND ( [User].[LastName] = 'Yo' OR [User].[LastName] = 'Smith' )
GROUP BY
[Campaign].[Title]
,CASE WHEN [Task].[Duration] <= 100 THEN '<100' WHEN [Task].[Duration] >= 100 AND [Task].[Duration] <= 200 THEN 'BETWEEN 100 AND 200' ELSE '>200' END
HAVING
COUNT(1) >= 0
ORDER BY
[Campaign].[Title]
,CASE WHEN [Task].[Duration] <= 100 THEN '<100' WHEN [Task].[Duration] >= 100 AND [Task].[Duration] <= 200 THEN 'BETWEEN 100 AND 200' ELSE '>200' END
我的猜测是,错误是由于选择列表中的case语句与分组中的语句不相同。我通常会在子查询中解析这些列,以便更容易读取和维护外部查询。
我在这里缺少的是,在替换参数之前,框架将首先验证它们的查询。
由于select和group by中的参数名称不同,因此框架假设它们具有不同的值,从而导致问题。
解决方案是重用相同的参数名称,以保证框架的值是相同的。