You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#调用存储过程返回结果与SSMS手动执行不一致问题

问题:C#调用存储过程返回值与SSMS执行结果不一致

参数完全相同的情况下,C#代码调用存储过程spCheckLabelExists返回0,但在SSMS中手动执行该存储过程却返回1。

C#原代码

using (SqlConnection connection = new SqlConnection(connStr))
{
    connection.Open();

    SqlCommand cmd = new SqlCommand("spCheckLabelExists", connection)
                    {
                        CommandType = CommandType.StoredProcedure
                    };

    cmd.Parameters.Add(SQLHelper.GetSqlParameter("@LabelName", SqlDbType.NVarChar, labelName));
    cmd.Parameters.Add(SQLHelper.GetSqlParameter("@IdParentLabel", SqlDbType.Int, labelId));

    SqlParameter returnValue = cmd.Parameters.Add("@ReturnValue", SqlDbType.Int);
    returnValue.Direction = ParameterDirection.ReturnValue;

    await cmd.ExecuteNonQueryAsync();

    result = (int)returnValue.Value;
} 

存储过程原代码

ALTER PROCEDURE [dbo].[spCheckLabelExists]
    @LabelName nvarchar(50),
    @IdParentLabel int
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @Exists bit = 0;

    IF EXISTS (SELECT 1 FROM [Label] 
               WHERE Name = @LabelName 
                 AND IdParentLabel = @IdParentLabel)
    BEGIN
        SET @Exists = 1;
    END
    ELSE
    BEGIN
        WITH LabelHierarchy AS 
        (
            SELECT IdLabel, IdParentLabel, Name
            FROM [Label]
            WHERE IdLabel = @IdParentLabel
            UNION ALL
            SELECT l.IdLabel, l.IdParentLabel, l.Name
            FROM [Label] l
            INNER JOIN LabelHierarchy h ON l.IdParentLabel = h.IdLabel
        )
        SELECT TOP 1 @Exists = 1 
        FROM LabelHierarchy 
        WHERE Name = @LabelName;
    END
    
    SELECT @Exists AS LabelExists;
END

问题原因

两者的核心差异在于返回值的获取方式不匹配:

  • SSMS执行存储过程时,显示的是最后SELECT @Exists AS LabelExists;输出的结果集,即@Exists的实际值(1)。
  • C#代码中,你尝试获取的是存储过程的Return Value(通过ParameterDirection.ReturnValue定义的参数),但存储过程未使用RETURN语句返回@Exists,SQL Server存储过程默认Return Value为0,因此C#拿到的是默认值。

解决方案

方案1:修改存储过程,添加RETURN语句返回结果

在存储过程末尾添加RETURN @Exists;,让Return Value能拿到正确结果:

ALTER PROCEDURE [dbo].[spCheckLabelExists]
    @LabelName nvarchar(50),
    @IdParentLabel int
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @Exists bit = 0;

    IF EXISTS (SELECT 1 FROM [Label] 
               WHERE Name = @LabelName 
                 AND IdParentLabel = @IdParentLabel)
    BEGIN
        SET @Exists = 1;
    END
    ELSE
    BEGIN
        WITH LabelHierarchy AS 
        (
            SELECT IdLabel, IdParentLabel, Name
            FROM [Label]
            WHERE IdLabel = @IdParentLabel
            UNION ALL
            SELECT l.IdLabel, l.IdParentLabel, l.Name
            FROM [Label] l
            INNER JOIN LabelHierarchy h ON l.IdParentLabel = h.IdLabel
        )
        SELECT TOP 1 @Exists = 1 
        FROM LabelHierarchy 
        WHERE Name = @LabelName;
    END
    
    SELECT @Exists AS LabelExists;
    RETURN @Exists; -- 添加此行,将@Exists作为存储过程Return Value返回
END

修改后原C#代码无需调整,即可正确获取返回值。

方案2:修改C#代码,获取存储过程输出的结果集

改用ExecuteScalarAsync()获取结果集的第一行第一列值(即SSMS显示的结果):

using (SqlConnection connection = new SqlConnection(connStr))
{
    connection.Open();

    SqlCommand cmd = new SqlCommand("spCheckLabelExists", connection)
                    {
                        CommandType = CommandType.StoredProcedure
                    };

    cmd.Parameters.Add(SQLHelper.GetSqlParameter("@LabelName", SqlDbType.NVarChar, labelName));
    cmd.Parameters.Add(SQLHelper.GetSqlParameter("@IdParentLabel", SqlDbType.Int, labelId));

    // 无需定义Return Value参数,直接获取结果集的第一行第一列
    var resultObj = await cmd.ExecuteScalarAsync();
    result = Convert.ToInt32(resultObj);
} 

此方案无需修改存储过程,仅调整C#代码的结果获取方式即可。

内容的提问来源于stack exchange,提问作者BlackCat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 09:33:11