【问题标题】:SqlCommand is returning an error when attempting to execute a query using c#SqlCommand 在尝试使用 c# 执行查询时返回错误
【发布时间】:2016-07-28 18:07:51
【问题描述】:

我正在开发一个项目,该项目将允许用户通过选择列来构建查询。

我的应用程序似乎工作正常并生成了正确的查询。但是当我执行查询时,我得到以下异常

列“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

【问题讨论】:

  • 错误显示Tasks.Duration,但我在您的SQL 查询中只看到Task.Duration。有没有漏掉的错别字?
  • 你能不能给我们正常的查询,不带参数。
  • @JonathonOgden 我认为这是因为表 Tasks 被别名为 Task
  • 我可能会做一个子查询,将持续时间转换为 3 个所需范围,然后对其进行分组。
  • @MikeA 您是否使用过 SQL Server Profiler 来查看最终查询是如何呈现给 SQL Server 的?

标签: c# sql-server sqlcommand


【解决方案1】:

我的猜测是该错误是由于您在选择列表中的 case 语句与您的 group by 中的不同。我通常做的是在子查询中解析这些列,以便更容易阅读和维护外部查询。

【讨论】:

  • 如果您查看我的查询,您将看到所选列中唯一的不同之处,分组依据是参数名称,但值相同。这可能是个问题吗?
  • @MikeA 为什么使用不同的参数?您不知道您可以在查询中多次使用参数吗?
  • @juharr 是的,我不知道我可以重复使用相同的参数!谢谢你的说明。但这会导致这个错误吗?
  • 我看不出任何其他原因。查询可能在解析参数之前被解析。
  • @MikeA 是的,因为它会在将参数替换为值之前进行检查。这是参数的要点之一,因此它可以解析查询,并且计划将被重用于不同的参数集。
【解决方案2】:

我在这里遗漏的是,框架将首先验证他们的查询,然后再替换参数。

由于 select 和 group by 中的参数名称不同,因此框架假定它们具有不同的值,从而导致问题。

解决方案是重用相同的参数名称,以向框架保证值是相同的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-06
    相关资源
    最近更新 更多