【问题标题】:Stored procedure doesn't return an int value存储过程不返回 int 值
【发布时间】:2015-03-12 13:04:31
【问题描述】:

MySql 过程代码:

CREATE DEFINER=`root`@`localhost` PROCEDURE `USP_CreateCliente`(IN nome_cliente VARCHAR(45))
BEGIN
    Select 20;
    INSERT INTO clienti ( nome_cliente )
    VALUES ( nome_cliente );
    Select id_cliente from clienti;
END

控制器页面中的C#代码:

ClienteInfo CI = new ClienteInfo();
DboUser objdbo = new DboUser();
int id_cliente = 0;

CI.nome_cliente = txtNomeCliente.Text;

id_cliente = objdbo.CreateClienteInfo(CI);

DboUser 类:

public int CreateClienteInfo(ClienteInfo CI)
{
        int result;
        MySqlConnection conn = new MySqlConnection();
        DbConnection db = new DbConnection();
        conn = db.ConnessioneDb();

        MySqlCommand cmd = new MySqlCommand(Costanti.StoredProcedures.USP_CreateCliente, conn);
        cmd.CommandType = CommandType.StoredProcedure;

        cmd.Parameters.AddWithValue("@nome_cliente", CI.nome_cliente);

        result = cmd.ExecuteNonQuery();
        conn.Close();
        return result;
    }

我希望我的 C# 代码在将客户 ID 插入数据库后检索它,这样我就可以将其保存到会话中,稍后在打印包含客户信息的文档的页面中再次检索它。

我的 id_cliente 返回 0,您是否注意到任何语法错误? 我是不是做错了什么?

我 90% 确定这是处理存储过程的问题,因为客户插入正确

【问题讨论】:

  • 为什么是 ExecuteNonQuery 而不是 executescaler 或 executereader?
  • 为什么 90% 确定?为什么不是100%?哈哈。是的,SP 和调用代码中也有问题。请参阅史蒂夫的回答。
  • 同时关闭finally块中的连接,因为执行数据库操作可能有异常。

标签: c# mysql select stored-procedures return


【解决方案1】:

改变这一行

result = cmd.ExecuteNonQuery();

result = Convert.ToInt32(cmd.ExecuteScalar());

但您也应该更改您的存储过程,因为它不会返回AUTO_INCREMENTid_cliente 为您生成的最后一个ID

CREATE DEFINER=`root`@`localhost` PROCEDURE `USP_CreateCliente`(IN nome_cliente VARCHAR(45))
BEGIN
    INSERT INTO clienti ( nome_cliente ) VALUES ( nome_cliente );
    Select LAST_INSERT_ID();
END

在 MySql 中,要获取生成的 auto_increment 值,您可以使用LAST_INSERT_ID(),接下来,您的 C# 代码不需要使用 ExecuteNonQuery,它只返回您更改、添加或删除的行数,但是您使用 ExecuteScalar 返回存储过程执行的最后一个 SELECT 命令的第一行的第一列。 (这是 SELECT LAST_INSERT_ID())

此外,要完成答案,您实际上并不需要存储过程来完成这种简单的工作。优势应该是最小的,而与要维护的不同软件相关的问题是不言而喻的。

您的 C# 代码可能是(删除了 DbConnection 类的用法,因为不清楚它的作用)

public int CreateClienteInfo(ClienteInfo CI)
{

    int result;
    string cmdText = @"INSERT INTO clienti ( nome_cliente ) VALUES ( nome_cliente );
                       Select LAST_INSERT_ID();";

    using(MySqlConnection conn = new MySqlConnection(....connectionstring .....))
    using(MySqlCommand cmd = new MySqlCommand(cmdText, conn);
    {
        conn.Open()
        cmd.Parameters.AddWithValue("@nome_cliente", CI.nome_cliente);
        result = Convert.ToInt32(cmd.ExecuteScalar())
        return result;
    }
}

在这里,您可以将批处理命令传递给您的 MySql 引擎,这意味着具有相同 MySqlCommand 的两个命令文本用分号分隔它们

【讨论】:

  • 我的 DbConnection 类里面只有连接字符串。在 DboUser 类中,我不仅有“创建客户”方法,还有“创建用户”、“更改密码”、“获取信息”(用于用户面板控件)等。如果我在 MySql 中更改密码或数据库名称,我将不得不更改 30 个连接字符串,使用我的 DbConnection 类我只做一次。这不是一个庞大的项目,我隔离了一些代码来向您展示我的问题,但有人告诉我使用存储过程,因为我的应用程序越来越大,总有一天我会遇到维护问题
  • 没问题,这只是一个老程序员的建议。存储过程并不总是可维护性场景的最佳答案。对于 DbConnection 类,我真的不知道该说什么。通常这些实用程序类会产生更多问题。 ORM 应该是一种更好的方法(搜索 Dapper。它在这个站点的后面并且是免费的)。咻
猜你喜欢
  • 1970-01-01
  • 2017-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-18
  • 1970-01-01
相关资源
最近更新 更多