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
相关产品推荐
相关产品推荐

