3

First of all I would like to thank anyone who reads this and answers. Your help is greatly appreciated!

I have been developing an ASP.NET web application in which I have need to read from and write to a database. For this I have been attempting to call, from my C# code, some stored procedures I have written. Specifically this one:

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;
}

The stored procedure I call was created with this SQL script:

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

I tested it on its own in SQL Server Management Studio, and it seems to work. However, upon stepping through my C# code I find a problem with the line

userExistsInDB = cmd.ExecuteNonQuery();

The stored procedure is supposed to return 1 or 0 if the specified user exists in the database or not, respectively, and as you can see userExistsInDB is initialized with -1. However after the line userExistsInDB = cmd.ExecuteNonQuery(); is executed userExistsInDB is never modified; it always retains the value -1. So it seems I am getting the return value incorrectly. What am I doing wrong?

EDIT:

Thanks to Leonel, I found a solution to the problem. First, I realized that the stored procedure I pasted above was not the correct procedure. It is not the one I am actually calling in my C# code, and when I tried Leonel's fix, it didn't work because I accidentally edited the procedure I pasted above instead of the one I actually call. Here is the actual stored procedure I was calling:

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

My solution is as follows: change this line

userExistsInDB = cmd.ExecuteNonQuery();

to

userExistsInDB = (int)cmd.ExecuteScalar();

and change the stored procedure to:

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
Tom
  • 67
  • 8
  • Code always reads better than a screenshot of it. Paste the actual source code and I'll help to format it properly. – abatishchev Nov 21 '14 at 04:13
  • Have you try with ExecuteScalar? Here is a brief explanation of the difference of ExecuteScalar and ExecuteNonQuery http://stackoverflow.com/questions/2974154/what-is-the-difference-between-executescalar-executereader-and-executenonquery – bsting Nov 21 '14 at 04:16
  • I have not tried that. I will, and let you know if it works. Thanks! – Tom Nov 21 '14 at 04:20
  • Found this, maybe useful for you. http://www.c-sharpcorner.com/Blogs/3935/executescalar-vs-executenonquery.aspx You can use the ExecuteNonQuery to perform catalog operations by executing UPDATE, INSERT, or DELETE statements. For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. For all other types of statements, the return value is -1. – bsting Nov 21 '14 at 04:21
  • I tried this: `userExistsInDB = (int)cmd.ExecuteScalar();` and the code threw this exception: An exception of type 'System.NullReferenceException' occurred in TaskBlasterDBAccessObjects.dll but was not handled in user code Additional information: Object reference not set to an instance of an object. – Tom Nov 21 '14 at 04:52

2 Answers2

1

Use SqlCommand.ExecuteScalar(); method from MSDN

For example:

userExistsInDB = (int)cmd.ExecuteScalar();

The example code will execute the SqlCommand and retrieve the first row of the table if exist and set the value of the variable into number of items in table. In this case you can remove the return statement and use the

SELECT * FROM logged_in_users WHERE "username" = @username

And also always close your connection after using it

con.Open();
userExistsInDB = cmd.ExecuteScalar();
con.Close();
Onel Sarmiento
  • 1,608
  • 3
  • 20
  • 46
  • 1
    Thanks, I will try that. Also: doesn't declaring the `SqlConnection` object in a `using` block take care of closing the connection for me when the block is completed? Or is closing the connection explicitly just better practice? – Tom Nov 21 '14 at 05:03
  • @Tom It's best practice to close your connection after execution. – Onel Sarmiento Nov 21 '14 at 05:05
  • I tried exactly what you said and was met with this exception: An exception of type 'System.NullReferenceException' occurred in TaskBlasterDBAccessObjects.dll but was not handled in user code Additional information: Object reference not set to an instance of an object. – Tom Nov 21 '14 at 05:23
  • 1
    I found out what I was doing wrong: I changed the line in my C# code to `userExistsInDB = (int)cmd.ExecuteScalar();` but I accidentally edited the wrong stored procedure. Actually, the stored procedure I posted above was the wrong stored procedure altogether. I have a different one called `tb_user_exists` that has a similar conditional statement to the one I posted above. This is the procedure I meant to call. So I changed the code in that procedure to what you suggested, and changed my C# code to what you suggested, and it worked like a charm! Thanks for the help! – Tom Nov 21 '14 at 21:18
-1

If you just getting one value, executeScalar() would be good enough. If you still have problem you can ask

String get;
Get=cmd.executescalar().tostring();
Rain
  • 231
  • 3
  • 12
  • I tried this: `String getVal = cmd.ExecuteScalar().ToString();` and the code threw an exception with this message: An exception of type 'System.NullReferenceException' occurred in TaskBlasterDBAccessObjects.dll but was not handled in user code Additional information: Object reference not set to an instance of an object. – Tom Nov 21 '14 at 04:46
  • I hope I did not misunderstood your question. Are you trying to get a return value from SQL database? Cause I just figure this problem out two weeks ago, I still have the source code for it. – Rain Nov 21 '14 at 04:52
  • I am trying to get a return value from a stored procedure that exists on a Microsoft SQL Server database. I call this stored procedure from my C# code. – Tom Nov 21 '14 at 05:00
  • Yeh, I got you. Umm do you have skype? Maybe I could share the source code with you – Rain Nov 21 '14 at 05:00
  • Can you share your current code again? So I can find the problem for you – Rain Nov 21 '14 at 05:01
  • This is what the method looks like with what you suggested http://pastebin.com/jm1cRJT2. When it gets to the line in question it throws an exception. The stored procedure is still the same as what it looks like in my original post. – Tom Nov 21 '14 at 05:15
  • I'm not a very experienced programmer either, I never seen anyone using the "using" thing.. But I think the problem is that you did not give your cmd a command. I'm going to get you the codes – Rain Nov 21 '14 at 05:18