首先,为了清楚起见,我认识到ExecuteNonQuery
只应用于UPDATE, INSERT, or DELETE
语句,而对于所有其他类型的语句,例如SELECT,返回值为-1。
我的问题是,为什么以下存储过程:
CREATE PROCEDURE `ExampleProc`(IN Name varchar(60), OUT ID bigint(20), OUT SP varchar(255))
BEGIN
SELECT id, sp INTO ID, SP FROM users WHERE username = Name;
END
使用ExecuteNonQuery
执行时:
using (var conn = new MySqlConnection("Secret"))
{
conn.Open();
using (var cmd = new MySqlCommand("ExampleProc", conn) { CommandType = CommandType.StoredProcedure })
{
cmd.Parameters.AddWithValue("Name", request.Name).MySqlDbType = MySqlDbType.VarChar;
cmd.Parameters.Add("ID", MySqlDbType.Int64).Direction = ParameterDirection.Output;
cmd.Parameters.Add("SP", MySqlDbType.VarChar).Direction = ParameterDirection.Output;
var returnVal = cmd.ExecuteNonQuery();
}
}
如果找不到名称的行,则会产生0 in returnVal
,如果找到,则会产生1
?根据我读过的所有文档,由于存储过程包含single SELECT statement
,我应该看到-1
无论如何返回。相反,它会返回受影响/找到的行数,这根据文档没有意义。
最后,我还尝试使用"SELECT *" instead of "SELECT id, sp INTO ID, SP"
。这似乎总是返回0
。仍然不是我期待的-1
。
答案 0 :(得分:1)
让我们了解ADO.Net中ExecuteNonQuery
API的工作原理,正如您从文档中了解的那样,它应提供受DML
查询影响的行数和Select
查询的-1。
但是内部工作是这样的,如果是Sql Server
,默认设置为Set NoCount Off
有助于写入TDS protocol
,修改的行数和Ado读取的数量相同.Net API,因此是正确的结果,这是ado.net
与Sql Server
的原生二进制整合的结果。更多详情请访问以下链接:
对于其他数据库,例如MySql
,Oracle
,不能保证相同的行为,因为它们的集成与Sql Server
不在同一级别。这是问题中发布的差异的主要原因,使其在整个数据库中保持一致,您可能希望依靠Output Parameter
在过程内部自动填充值,因为每个数据库都有机制来计算超出更新的行数