简体   繁体   中英

How do I use ExecuteScalar with a stored Procedure?

I'm trying to get a count of column records in a Sql database and show the result in a MessageBox.

This is my code:

public DataTable CheckIfNameExist(string name)
{
    con = Connect();
    cmd = new SqlCommand();
    cmd.Connection = con;
    cmd.CommandText = "spCheckIfNameExist";
    cmd.Parameters.AddWithValue("@Name", SqlDbType.NVarChar).Value = name;
    MessageBox.Show(name);

    Int32 totalNames = (Int32) cmd.ExecuteScalar();
    string tNames = totalNames.ToString();

    MessageBox.Show(tNames);
}

And this is my sp:

@Name nvarchar(50) = null
As
Begin
SELECT COUNT(*) from OrdersSent where CustomerName LIKE @Name + '%'
End

Problem:

It always returns 0.

There are a couple of errors in your code: You should write it as:

cmd.CommandText = "spCheckIfNameExist";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@Name", SqlDbType.NVarChar).Value = name;

First you need to tell the ADO engine that you are calling a stored procedure and not a simple command text, but you also need to use Add instead of AddWithValue to be precise on the type of the parameter passed to the SP. Your code creates a parameter int becase the second parameter of the AddWithValue is the Value of the parameter not the type.

You need to specify the type of your command like this:

cmd.CommandText = "spCheckIfNameExist";
cmd.CommandType = CommandType.StoredProcedure;

See also:

What is the benefit of using CommandType.StoredProcedure versus using CommandType.Text?

Although specify the type directly and use the Value property is more better than AddWithValue :

cmd.Parameters.Add("@Name", SqlDbType.NVarChar).Value = name;

The following article could be also interesting:

https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/

You have a few problems in the c# code - the most important is probably this:

cmd.Parameters.AddWithValue("@Name", SqlDbType.NVarChar).Value = name;

Don't use AddWithValue . Use Add .

Also, you didn't specify the command type - the default is Text .
And you are using fields for SqlConnection and SqlCommand - which is also the wrong thing to do. You should create and dispose both of them inside each method you are using them.

A better version of your code would be this:

using(var con = new SqlConnection(ConnectionString))
{
    using(var cmd = new SqlCommand("spCheckIfNameExist", con))
    {
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add("@Name", SqlDbType.NVarChar).Value = name;
        con.Open();
        var tNames = cmd.ExecuteScalar().ToString();
    }
}

Another thing that puzzles me is why a method called CheckIfNameExist returns a DataTable . I would expect it to simply return a bool .

If you really only want to check if the name exists, you can do this better on both the SQL level and the c# level.

A better SQL would be something like this:

SELECT CAST(CASE WHEN EXISTS(
    SELECT 1 
    FROM OrdersSent 
    WHERE CustomerName LIKE @Name + '%'
) THEN 1 ELSE 0 END AS bit)

And on the c# level, bit translates directly to bool, so the code can simple be this:

public bool CheckIfNameExist(string name)
{
    using(var con = new SqlConnection(ConnectionString))
    {
        using(var cmd = new SqlCommand("spCheckIfNameExist", con))
        {
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Add("@Name", SqlDbType.NVarChar).Value = name;
            con.Open();
            return (bool)cmd.ExecuteScalar();
        }
    }
}

And another note - you should avoid using the sp prefix for stored procedures.
Microsoft have reserved this prefix for built in system procedures. For more information, read Aaron Bertrand's Is the sp_ prefix still a no-no? , where you'll see that the short answer to this question is "Yes".

The sp_ prefix does not mean what you think it does: most people think sp stands for "stored procedure" when in fact it means "special." Stored procedures (as well as tables and views) stored in master with an sp_ prefix are accessible from any database without a proper reference (assuming a local version does not exist). If the procedure is marked as a system object (using sp_MS_marksystemobject (an undocumented and unsupported system procedure that sets is_ms_shipped to 1), then the procedure in master will execute in the context of the calling database.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM