如何将ExecuteScalar与存储过程一起使用?

时间:2018-12-13 08:10:34

标签: c# sql-server stored-procedures ado.net executescalar

我正在尝试获取Sql数据库中的列记录数,并将结果显示在MessageBox中。

这是我的代码:

$this->db->where_in('column_1', array(1, 2));
$this->db->where_in('column_2', array(2, 13));

这是我的sp:

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

问题:

它总是返回0。

3 个答案:

答案 0 :(得分:2)

您的代码中有几个错误: 您应该将其写为:

//Iterate through the HashMap
for(Entry<?, ?> configEntry : pluginConf.entrySet()){
    //Get a string from the selected key that contains only lower-case letters and periods
    String entryKey = configEntry.getKey().toString().replaceAll("[^a-zA-Z.]", "").toLowerCase();

    //Search for join messages
    if(entryKey.equals("messages.join")){
        //Get the key name of the current entry
        String joinKeyName = configEntry.getKey().toString();

        //Create a join message object
        JoinMessage newJoinMessage = new JoinMessage(,
            configData.getString(joinKeyName + ".message")
        );

        //Add the join message object to the join message ArrayList
        joinMessages.add(newJoinMessage);

        //Add to the join message quantity
        joinMsgQuantity ++;
    }
}

首先,您需要告诉ADO引擎您正在调用存储过程,而不是简单的命令文本,但是您还需要使用Add代替AddWithValue来精确传递给SP的参数类型。您的代码会创建一个int参数,前提是AddWithValue的第二个参数是参数的Value而不是类型。

答案 1 :(得分:1)

您需要像这样指定命令的类型:

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

另请参阅:

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

尽管直接指定类型并使用Value属性比AddWithValue更好:

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

以下文章也可能很有趣:

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

答案 2 :(得分:0)

您在C#代码中遇到了一些问题-最重要的可能是这样:

upload_only=3

Don't use AddWithValue.使用cmd.Parameters.AddWithValue("@Name", SqlDbType.NVarChar).Value = name;

此外,您没有指定命令类型-默认为Add
而且您正在使用TextSqlConnection的字段-这也是错误的做法。您应该在使用它们的每种方法中创建和处置它们。

更好的代码版本是这样:

SqlCommand

令我困惑的另一件事是,为什么名为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(); } } 的方法返回CheckIfNameExist。我希望它只返回一个DataTable

如果您真的只想检查名称是否存在,则可以在SQL级别和c#级别上更好地做到这一点。

更好的SQL应该是这样的:

bool

在c#级别上,位直接转换为bool,因此代码可以很简单:

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

还有另外一个注意事项-您应该避免对存储过程使用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(); } } } 前缀。
Microsoft已为内置系统过程保留了此前缀。 有关更多信息,请阅读亚伦·伯特兰德(Aaron Bertrand)的Is the sp_ prefix still a no-no?,您会发现该问题的简短答案是“是”。

  

sp_前缀并不表示您的想法:大多数人认为sp代表“存储过程”,而实际上却表示“特殊”。在没有适当引用的情况下(假定不存在本地版本),可以从任何数据库访问具有sp_前缀的master中存储的存储过程(以及表和视图)。如果该过程被标记为系统对象(使用sp_MS_marksystemobject(将is_ms_shipped设置为1的未记录且不受支持的系统过程),则master中的过程将在调用数据库的上下文中执行。