【问题标题】:Understanding ExecuteNonQuery's return value了解 ExecuteNonQuery 的返回值
【发布时间】:2016-12-23 14:34:52
【问题描述】:

首先,为了清楚起见,我知道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();
    }
}

如果没有找到带有 Name 的行,则返回 0 in returnVal,如果找到则返回 1?根据我阅读的所有文档,由于存储过程包含single SELECT statement,因此无论如何我都应该看到-1 被返回。相反,它返回受影响/找到的行数,根据文档,这没有意义。

最后,我也试过只使用"SELECT *" instead of "SELECT id, sp INTO ID, SP"。这似乎总是返回0。仍然不是我期待的-1

【问题讨论】:

  • 检查链接 msdn.microsoft.com/en-in/library/ms188774.aspx 以获取 Select 语句尝试设置 Set RowCount <Number> 并进行测试。另请注意您提到的行为是特定于 Sql Server 的,对于不同的数据库可能会有不同的行为

标签: c# mysql stored-procedures


【解决方案1】:

让我们了解 ADO.Net 中 ExecuteNonQuery API 的工作原理,正如您从文档中了解的那样,它应提供作为 DML 查询的一部分受影响的行数,为 Select 提供 -1询问。

但是内部工作是这样的,在Sql Server 的情况下,默认设置是Set NoCount Off 有助于写入TDS protocol,修改的行数和相同的行数由 Ado.Net API 读取,因此正确的结果,这是ado.netSql Server 的本机二进制集成的结果。更多详情请点击以下链接:

Ado.Net TDS Protocol

SET NOCOUNT ON usage

当涉及到其他数据库时,例如MySqlOracle,不能保证相同的行为,因为它们的集成与Sql Server 不同。这是问题中发布的差异的主要原因,为了使其在整个数据库中保持一致,您可能希望依靠Output Parameter 在过程内部自动填充值,因为每个数据库都有机制来找出更新的行数

【讨论】:

  • 感谢您的回答。存在差异似乎很奇怪,特别是因为在 MySQL 文档中描述了相同的行为:dev.mysql.com/doc/dev/connector-net/html/…。此外,作为测试,我没有使用存储过程,而是使用“SELECT * FROM users”设置 MySqlCommand 并返回 -1,因此存储过程的工作方式似乎存在问题。有什么建议吗?
  • @Eaton 需要更深入地了解更详细的信息,尽管您发布的链接提供了相同的详细信息,但我确信有一些方面或设置,例如 NoCountONSql Server My Sql,需要探索才能理解行为的偏差
  • 我做了一些研究,但找不到任何东西。在 MySQL 中似乎没有以任何形式使用 NOCOUNT。
  • NOCOUNTSql Server 特定的,必须有另一种选择,要点仍然是正确的结果需要理解 Sql Server 中所做的实现,只有数据连接器团队可以解释。我记得Oracle 不能与ExecuteNonQuery 一起正常工作,因为ODP.Net 没有像Sql Server 这样的选项
  • 这对我来说看起来像是一个错误。我尝试使用 ExecuteReader,它返回的 MySqlDataReader 的“HasRows”属性为真,尽管它应该为假,因为我传入了一个虚假的用户名。有趣的是,使用返回的 MySqlDataReader 的“Read”方法第一次返回 false。在这一点上,我想我将只使用 Read 来确定我的存储过程中的 SELECT 是否找到任何东西,因为这些其他属性和返回值似乎不可靠。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-31
  • 2016-02-28
  • 1970-01-01
  • 2012-12-24
  • 1970-01-01
  • 2011-12-28
相关资源
最近更新 更多