C#中调用存储过程的合法示例请求:MYSQL

4

我已经花了大约7个小时通过试错来弄清楚这个问题。我看到的所有在线示例都不起作用,或者不适用,或者只显示我正在寻找的一半。

以下是我的要求: 1. MYSQL中一个使用一个IN参数和一个OUT参数的简单存储过程示例。 2. Visual Studio中一个运行良好的(非常重要,因为在线示例有时无法工作...)使用C#的调用示例。可以是文本调用或存储过程命令类型。 3. AddWithValue已被弃用。 4. 我很想看到输出参数确实有效。

如果在MYSQL和Visual Studio中无法实现,那么也请告知。

MYSQL文档对此特定示例不够详细。请不要讨论Visual Studio或C#的缺点。

先提前感谢您!:)

编辑:

这是我目前已经完成的,但它不起作用!!!

MYSQL方面,使用HeidiSQL:

CREATE DEFINER=`root`@`localhost` PROCEDURE `login`(IN `stuff` VARCHAR(50), IN `pass` VARCHAR(50), OUT `param3` INT)
    LANGUAGE SQL
    NOT DETERMINISTIC
    CONTAINS SQL
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN

    set param3 = 0;
    set param3 = (select count(*) from users where username=stuff and userpassword=pass);
    select @param3;

END

在 C# 方面,我尝试获取这个 OUT 参数。经过多次迭代后,我剖析了该函数曾经具有的功能,将其简化为两个问题:1. OUT 参数无法正常工作,2. 尽管 Visual Studio 传递了 IN 参数,但 SQL 拒绝识别它们。

protected void Login_Authenticate(object sender, AuthenticateEventArgs e)
    {
        using (MySqlConnection con = new MySqlConnection(strcon))
        {
            con.Open();

            MySqlCommand com = new MySqlCommand("CALL login(@stuff, @pass, @param3);", con);
            com.CommandType = CommandType.Text;
            com.Parameters.Add("@stuff", MySqlDbType.VarChar);
            com.Parameters["@stuff"].Value = Login.UserName;
            com.Parameters.Add("@pass", MySqlDbType.VarChar);
            com.Parameters["@pass"].Value = Login.Password;

            try
            {
                obj = com.ExecuteScalar();
                objparam = com.Parameters["param3"].Value;
                if (Convert.ToInt32(obj) != 0)
                {
                    Response.Redirect("Welcome.aspx");
                }
                else
                {
                    Login.PasswordRequiredErrorMessage = "invalid user name and password";
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            con.Close();
        }
    }

1
重新开始编辑你的问题,因为它即将关闭。展示你已经想到的最接近的解决方案。 - Drew
1
我已经编辑过了,展示了我当前的迭代版本,但它仍然无法工作。这是我能想到的最接近的解决方案。 - paladin law
感谢您展示了您所尝试的内容。那个特定的问题很难作为一个解决方案来组合。请注意,MySQL .NET连接器最近添加了处理OUT参数的功能。我不知道是多久之前,所以我目前正在使用最新的连接器版本6.9.9.0。 - Drew
哦...这就解释了为什么示例和文档不存在。耶,前沿技术!哈哈 - paladin law
我有一个文档参考:5.10.1 使用 Connector/Net 中存储的例程 - Drew
2个回答

5
我相信代码和图片比我说的更有意义。
C# 数据库层(数据库层有一个连接字符串conn):
// Note: this is an instance (myDB in terms of the GUI Object)

using System.Data;
using MySql.Data.MySqlClient;
...
...
public long MultBySeven(long theNum)
{   // Call a Mysql Stored Proc named "multBy7"
    // which takes an IN parameter, Out parameter (the names are important. Match them)
    // Multiply the IN by 7 and return the product thru the OUT parameter

    long lParam = 0;
    using (MySqlConnection lconn = new MySqlConnection(connString))
    {
        lconn.Open();
        using (MySqlCommand cmd = new MySqlCommand())
        {
            cmd.Connection = lconn;
            cmd.CommandText = "multBy7"; // The name of the Stored Proc
            cmd.CommandType = CommandType.StoredProcedure; // It is a Stored Proc

            // Two parameters below. An IN and an OUT (myNum and theProduct, respectively)
            cmd.Parameters.AddWithValue("@myNum", theNum); // lazy, not specifying ParameterDirection.Input;
            cmd.Parameters.AddWithValue("@theProduct", MySqlDbType.Int32);
            cmd.Parameters["@theProduct"].Direction = ParameterDirection.Output; // from System.Data
            cmd.ExecuteNonQuery(); // let it rip
            Object obj = cmd.Parameters["@theProduct"].Value;
            lParam = (Int32)obj;    // more useful datatype
        }
    }
    return (lParam);
}

C# GUI测试层:

private void btnTestInOut_Click(object sender, EventArgs e)
{   // This GUI Layer call thru the use of a business object or data layer object (`myDB`)
    long localHere = myDB.MultBySeven(11);
}

存储过程(取一个数字,乘以7):

DROP PROCEDURE IF EXISTS multBy7;
DELIMITER $
CREATE PROCEDURE multBy7
(   IN myNum INT,
    OUT theProduct INT
)
BEGIN
    SET theProduct=myNum*7;
END$
DELIMITER ;

调试视图(读取:它有效。11x7=77):

输入图像描述

MySQL Connector 6.9.9.0 / Visual Studio 2015: 输入图像描述

另请参见5.10.1使用存储例程从Connector/Net中使用,年龄未知。


感谢您,我意识到我没有安装所有必要的软件包。除了修复代码外,我还需要NuGet mysql Web、entity framework和connector。我以为我之前已经做对了,但显然不是这样。 - paladin law

1
您应该设置一个参数的引用。
var param3 = new MySqlParameter();
param3.Direction = ParameterDirection.Output;
param3.DbType = // whatever the dbtype for int is or whatever you need.
param3.ParameterName = "param3";

com.Parameters.Add(param3);

在你的try块中,插入


var result = com.ExecuteReader(); // or com.ExecuteScalar();

执行此操作后,您的参数应该已经填充了值,您也应该能够读取存储过程结果(select)。
var paramResult = param3.Value;

阅读 SP 的结果可以作为读取器或标量来完成。
// execute reader
while (result.Read()) {
    int value = result.GetInt32(0)); 
} /* read returned values in result */ 

// execute scalar
int value;
if (int.TryParse($"{result}", out value)) {
    /* do something with value */ 
}

/************************************************/

这个代码块会帮助你到达你需要去的地方。

        const string strcon = "whatevs";

        using (MySqlConnection con = new MySqlConnection(strcon))
        {
            const string sql = "login";

            MySqlCommand com = new MySqlCommand(sql, con);
            com.CommandType = CommandType.StoredProcedure;

            var stuffParam = new MySqlParameter("stuff", stuffValue);
            var passParam = new MySqlParameter("pass", passValue);
            var param3Param = new MySqlParameter();
            param3Param.ParameterName = "param3";
            param3Param.DbType = DbType.Int32;
            param3Param.Direction = ParameterDirection.Output;

            com.Parameters.Add(stuffParam);
            com.Parameters.Add(passParam);
            com.Parameters.Add(param3Param);

            try
            {
                var scalarResult = com.ExecuteScalar();

                // because you used select @param3 in your sp.
                int value;
                if (int.TryParse($"{scalarResult}", out value))
                {
                    //do something with value
                }

                //// because you used select @param3 in your sp.
                //var readerResult = com.ExecuteReader();

                //if (readerResult.Read())
                //{
                //    // 
                //    value = readerResult.GetInt32(0);
                //}

                int param3Returned;
                if(int.TryParse($"{param3Param.Value}", out param3Returned))
                {
                    // do something with param3Returned
                }
            }
            catch (Exception ex)
            {
                // do something with ex
            }
        }

这看起来非常接近可能会起作用的东西。我现在正在修改我的代码。谢谢!scalarResult是哪个属性?智能感知显示它不存在。 - paladin law
哦,忽略关于标量结果的最后一个问题。 - paladin law
我觉得我现在离答案非常接近了。我使用了你的代码,但现在它给我一个新的错误。它说:执行期间出现异常:'login' 参数'stuff'未定义。只要我执行ExecuteScalar或ExecuteReader。 - paladin law
我已经更新了参数定义的代码 - 不需要使用@符号。抱歉。 - Rick the Scapegoat
1
非常感谢!我花了很多时间来尝试解决这个问题!去掉@就可以了。 - paladin law

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接