C# 如何从对存储过程的调用中正确捕获返回值

C# 如何从对存储过程的调用中正确捕获返回值,c#,.net,sql-server,stored-procedures,return-value,C#,.net,Sql Server,Stored Procedures,Return Value,首先,我要感谢所有读到这篇文章并给出答案的人。非常感谢你的帮助 我一直在开发一个ASP.NET web应用程序,在其中我需要对数据库进行读写操作。为此,我一直试图从我的C代码调用一些我编写的存储过程。具体来说,这一点: public static bool userExistsInDB(string username) { int userExistsInDB = -1; using (SqlConnection con = new SqlConnection(DBConfig.

首先,我要感谢所有读到这篇文章并给出答案的人。非常感谢你的帮助

我一直在开发一个ASP.NET web应用程序,在其中我需要对数据库进行读写操作。为此,我一直试图从我的C代码调用一些我编写的存储过程。具体来说,这一点:

public static bool userExistsInDB(string username)
{
    int userExistsInDB = -1;
    using (SqlConnection con = new SqlConnection(DBConfig.DbConnectString))
    {
        using (SqlCommand cmd = new SqlCommand("tb_user_exists", con))
        {
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Add("@username", SqlDbType.VarChar).Value = username;
            con.Open();
            userExistsInDB = cmd.ExecuteNonQuery();
        }
    }
    return userExistsInDB == 1;
}
我调用的存储过程是使用以下SQL脚本创建的:

CREATE PROCEDURE tb_is_logged_in
    @username VARCHAR(20)
AS
IF(EXISTS(SELECT * FROM logged_in_users WHERE "username" = @username))
BEGIN
    RETURN 1; 
END
ELSE
BEGIN
    RETURN 0; 
END
我在SQLServerManagementStudio中单独测试了它,它似乎可以工作。然而,在我的C代码中,我发现这行代码有问题

userExistsInDB = cmd.ExecuteNonQuery();
如果指定的用户是否存在于数据库中,则存储过程应分别返回1或0,如您所见,
userExistsInDB
-1
初始化。但是在
userExistsInDB=cmd.ExecuteNonQuery()行之后被执行
userExistsInDB
从未被修改;它始终保留值
-1
。因此,似乎我得到的返回值不正确。我做错了什么

编辑:

多亏了莱昂内尔,我找到了解决问题的办法。首先,我意识到上面粘贴的存储过程不是正确的过程。它不是我在C#代码中实际调用的程序,当我尝试Leonel的修复程序时,它不起作用,因为我不小心编辑了我上面粘贴的过程,而不是我实际调用的过程。下面是我调用的实际存储过程:

CREATE PROCEDURE tb_user_exists
    @username VARCHAR(20)
AS
IF(EXISTS (SELECT * FROM users WHERE username = @username))
BEGIN
    RETURN 1;  
END
ELSE
BEGIN
    RETURN 0; 
END
我的解决办法如下:改变这一行

userExistsInDB = cmd.ExecuteNonQuery();

并将存储过程更改为:

CREATE PROCEDURE tb_user_exists
    @username VARCHAR(20)
AS
IF(EXISTS (SELECT * FROM users WHERE username = @username))
BEGIN
    SELECT 1;  
END
ELSE
BEGIN
    SELECT 0; 
END

如果只得到一个值,executeScalar()就足够了。如果你还有问题,你可以问

String get;
Get=cmd.executescalar().tostring();

使用
SqlCommand.ExecuteScalar()来自的方法

例如:

userExistsInDB = (int)cmd.ExecuteScalar();
示例代码将执行
SqlCommand
,检索表的第一行(如果存在),并将变量的值设置为表中的项数。在这种情况下,您可以删除return语句并使用

SELECT * FROM logged_in_users WHERE "username" = @username
并且在使用后始终关闭您的连接

con.Open();
userExistsInDB = cmd.ExecuteScalar();
con.Close();

代码总是比屏幕截图读得好。粘贴实际的源代码,我将帮助正确格式化。您尝试过ExecuteScalar吗?下面是ExecuteScalar和ExecuteOnQuery区别的简要说明,我还没有尝试过。我会的,如果行得通,就告诉你。谢谢找到这个,也许对你有用。您可以使用ExecuteOnQuery通过执行UPDATE、INSERT或DELETE语句来执行目录操作。对于UPDATE、INSERT和DELETE语句,返回值是受命令影响的行数。对于所有其他类型的语句,返回值为-1。我尝试了以下方法:
userExistsInDB=(int)cmd.ExecuteScalar()和代码引发了此异常:TaskBlasterDBAccessObjects.dll中发生了类型为“System.NullReferenceException”的异常,但未在用户代码中处理其他信息:对象引用未设置为对象的实例。我尝试了以下操作:
String getVal=cmd.ExecuteScalar().ToString()和代码引发了一个异常,并显示以下消息:TaskBlasterDBAccessObjects.dll中发生了“System.NullReferenceException”类型的异常,但未在用户代码中处理其他信息:对象引用未设置为对象的实例。希望我没有误解您的问题。您正在尝试从SQL数据库获取返回值吗?因为我两周前刚刚解决了这个问题,我仍然有它的源代码。我正在尝试从Microsoft SQL Server数据库中存在的存储过程中获取返回值。我用我的C代码调用这个存储过程。是的,我明白了。嗯,你有skype吗?也许我可以和你分享源代码你能再分享一下你现在的代码吗?所以我可以帮你找到问题,汉克斯,我会试试的。另外:在使用
块的
中声明
SqlConnection
对象时,是否需要在块完成后为我关闭连接?还是显式关闭连接只是更好的做法?@Tom执行后关闭连接是最好的做法。我完全按照您所说的做了尝试,但遇到了此异常:TaskBlasterDBAccessObjects.dll中出现了类型为“System.NullReferenceException”的异常,但未在用户代码中处理其他信息:Object引用未设置为对象的实例。我发现我做错了什么:我将C#code中的行更改为
userExistsInDB=(int)cmd.ExecuteScalar()但我不小心编辑了错误的存储过程。实际上,我上面发布的存储过程完全是错误的存储过程。我有一个不同的名为
tb\u user\u exists
的语句,它的条件语句与我上面发布的语句类似。这就是我想说的程序。因此,我将该过程中的代码更改为您建议的代码,并将我的C#代码更改为您建议的代码,它工作起来非常有魅力!谢谢你的帮助!
con.Open();
userExistsInDB = cmd.ExecuteScalar();
con.Close();