[英]How do I use ExecuteScalar with a stored Procedure?
我正在尝试获取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);
}
这是我的sp:
@Name nvarchar(50) = null
As
Begin
SELECT COUNT(*) from OrdersSent where CustomerName LIKE @Name + '%'
End
问题:
它总是返回0。
您的代码中有几个错误:您应将其编写为:
cmd.CommandText = "spCheckIfNameExist";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@Name", SqlDbType.NVarChar).Value = name;
首先,您需要告诉ADO引擎您正在调用存储过程,而不是简单的命令文本,但是您还需要使用Add而不是AddWithValue来精确传递给SP的参数类型。 您的代码创建了一个int参数,假设AddWithValue的第二个参数是参数的Value而不是类型。
您需要像这样指定命令的类型:
cmd.CommandText = "spCheckIfNameExist";
cmd.CommandType = CommandType.StoredProcedure;
也可以看看:
与使用CommandType.Text相比,使用CommandType.StoredProcedure有什么好处?
尽管直接指定类型并使用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/
您在C#代码中遇到了一些问题-最重要的问题可能是:
cmd.Parameters.AddWithValue("@Name", SqlDbType.NVarChar).Value = name;
不要使用AddWithValue
。 使用Add
。
另外,您没有指定命令类型-默认为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应该是这样的:
SELECT CAST(CASE WHEN EXISTS(
SELECT 1
FROM OrdersSent
WHERE CustomerName LIKE @Name + '%'
) THEN 1 ELSE 0 END AS bit)
在c#级别上,bit直接转换为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已为内置系统过程保留了此前缀。 有关更多信息,请阅读Aaron Bertrand的《 sp_前缀是否仍然是? ,您会看到此问题的简短答案是“是”。
sp_前缀并不表示您的想法:大多数人认为sp代表“存储过程”,而实际上却表示“特殊”。 在没有适当引用的情况下(假定不存在本地版本),可以从任何数据库访问具有sp_前缀的master中存储的存储过程(以及表和视图)。 如果该过程被标记为系统对象(使用sp_MS_marksystemobject(将is_ms_shipped设置为1的未记录且不受支持的系统过程),则master中的过程将在调用数据库的上下文中执行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.