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

C# 如何将ExecuteScalar与存储过程一起使用?,c#,sql-server,stored-procedures,ado.net,executescalar,C#,Sql Server,Stored Procedures,Ado.net,Executescalar,我试图获取Sql数据库中的列记录计数,并在MessageBox中显示结果 这是我的代码: public DataTable CheckIfNameExist(string name) { con = Connect(); cmd = new SqlCommand(); cmd.Connection = con; cmd.CommandText = "spCheckIfNameExist"; cmd.Parameters.AddWithValue("@Nam

我试图获取Sql数据库中的列记录计数,并在MessageBox中显示结果

这是我的代码:

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);
}
@Name nvarchar(50) = null
As
Begin
SELECT COUNT(*) from OrdersSent where CustomerName LIKE @Name + '%'
End
这是我的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);
}
@Name nvarchar(50) = null
As
Begin
SELECT COUNT(*) from OrdersSent where CustomerName LIKE @Name + '%'
End
问题:


它总是返回0。

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

cmd.CommandText = "spCheckIfNameExist";
cmd.CommandType = CommandType.StoredProcedure;
SELECT CAST(CASE WHEN EXISTS(
    SELECT 1 
    FROM OrdersSent 
    WHERE CustomerName LIKE @Name + '%'
) THEN 1 ELSE 0 END AS bit)
另见:

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

cmd.Parameters.Add("@Name", SqlDbType.NVarChar).Value = name;
下面的文章可能也很有趣:


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

cmd.CommandText = "spCheckIfNameExist";
cmd.CommandType = CommandType.StoredProcedure;
SELECT CAST(CASE WHEN EXISTS(
    SELECT 1 
    FROM OrdersSent 
    WHERE CustomerName LIKE @Name + '%'
) THEN 1 ELSE 0 END AS bit)
另见:

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

cmd.Parameters.Add("@Name", SqlDbType.NVarChar).Value = name;
下面的文章可能也很有趣:


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

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

另外,您没有指定命令类型-默认值为
Text

您正在为
SqlConnection
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
。我希望它只返回一个
bool

如果您真的只想检查名称是否存在,那么在SQL级别和c#级别上都可以做得更好

更好的SQL应该是这样的:

cmd.CommandText = "spCheckIfNameExist";
cmd.CommandType = CommandType.StoredProcedure;
SELECT CAST(CASE WHEN EXISTS(
    SELECT 1 
    FROM OrdersSent 
    WHERE CustomerName LIKE @Name + '%'
) THEN 1 ELSE 0 END AS bit)
在c#级上,位直接转换为bool,因此代码可以简单如下:

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();
        }
    }
}
另一个注意事项-应避免在存储过程中使用
sp
前缀。
Microsoft已为内置系统过程保留此前缀。 要了解更多信息,请阅读亚伦·伯特兰的书,在书中你会看到这个问题的简短答案是“是”

sp_uu前缀并不是您所认为的那样:大多数人认为sp代表“存储过程”,而实际上它的意思是“特殊”。使用sp_uu前缀存储在master中的存储过程(以及表和视图)可以从任何数据库访问,而无需适当的引用(假设本地版本不存在)。如果该过程被标记为系统对象(使用sp_MS_marksystemobject(一个未记录且不受支持的系统过程,设置为isu MS_附带到1),则master中的过程将在调用数据库的上下文中执行


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

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

另外,您没有指定命令类型-默认值为
Text

您正在为
SqlConnection
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
。我希望它只返回一个
bool

如果您真的只想检查名称是否存在,那么在SQL级别和c#级别上都可以做得更好

更好的SQL应该是这样的:

cmd.CommandText = "spCheckIfNameExist";
cmd.CommandType = CommandType.StoredProcedure;
SELECT CAST(CASE WHEN EXISTS(
    SELECT 1 
    FROM OrdersSent 
    WHERE CustomerName LIKE @Name + '%'
) THEN 1 ELSE 0 END AS bit)
在c#级上,位直接转换为bool,因此代码可以简单如下:

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();
        }
    }
}
另一个注意事项-应避免在存储过程中使用
sp
前缀。
Microsoft已为内置系统过程保留此前缀。 要了解更多信息,请阅读亚伦·伯特兰的书,在书中你会看到这个问题的简短答案是“是”

sp_uu前缀的含义与您想象的不同:大多数人认为sp代表“存储过程”,而实际上它的意思是“特殊”。使用sp_uu前缀存储在master中的存储过程(以及表和视图)可以从任何数据库访问,而无需适当的引用(假设本地版本不存在)。如果该过程被标记为系统对象(使用sp_MS_marksystemobject(未记录且不受支持的系统过程,设置为is_MS_配送至1),则master中的过程将在调用数据库的上下文中执行


您的代码中有几个错误: 你应该这样写:

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

首先,您需要告诉ADO引擎您正在调用一个存储过程,而不是一个简单的命令文本,但是您还需要使用Add而不是AddWithValue来精确地确定传递给SP的参数的类型。您的代码创建了一个参数int,因为AddWithValue的第二个参数是参数的值,而不是类型e、 您的代码中有几个错误: 你应该这样写:

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

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

您在
中使用参数的方式不正确,比如
,这就是查询本身返回0结果的原因。在cmd.executeScalar()之前添加cmd.CommandType=CommandType.Procedure可能是重复的@Arjun这是CommandType.StoredProcedure,但我怀疑这里还有其他原因,因为该错误会导致Exception@Steve,我只是给了他一个想法..是的,我也在想同样的事情..但是为什么代码在这种情况下没有引发异常,而是给他0结果您在
中使用参数的方式不正确ct…这就是查询本身返回0结果的原因。在cmd.executeScalar()@Arjun之前添加cmd.CommandType=CommandType.procedu可能是重复的