You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ASP.NET的C#代码中获取MySQL存储过程的返回值

解决MySQL存储过程输出参数在C#中获取的问题

首先咱们先修正你的MySQL存储过程——原存储过程里的输出参数赋值方式有误,多余的SELECT结果集也会干扰C#端的读取逻辑:

修正后的MySQL存储过程

DELIMITER $$
CREATE PROCEDURE Validate_User(
    IN $Username NVARCHAR(20), 
    IN $_Password NVARCHAR(20),
    OUT $UserId INT 
) 
BEGIN
    DECLARE $UserId1 INT;
    DECLARE $LastLoginDate DATE;
    DECLARE roles varchar(20);
    
    IF EXISTS(SELECT * FROM Users WHERE Username = $Username) THEN
        IF EXISTS(SELECT * FROM Users WHERE Username = $Username AND _Password = $_Password) THEN
            -- 验证通过,返回实际用户ID(根据你的Users表结构调整字段名)
            SELECT UserId INTO $UserId FROM Users WHERE Username = $Username;
        ELSE
            -- 密码错误,标记状态为-2
            SET $UserId = -2;
        END IF;
    ELSE
        -- 用户不存在,标记状态为-3
        SET $UserId = -3;
    END IF;
END $$
DELIMITER ;

说明:原存储过程里用SELECT $UserId= -1是错误的赋值方式,应该用SET语句给输出参数赋值;同时去掉了多余的SELECT *,避免产生额外结果集干扰C#端处理。

修正后的C#调用代码

protected void Button1_Click(object sender, EventArgs e)
{
    int userId;
    string roles = string.Empty;
    
    // 确保cmd和con是已初始化的MySqlCommand、MySqlConnection对象
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.CommandText = "Validate_User";
    
    // 添加输入参数,建议Trim去除首尾空格
    cmd.Parameters.AddWithValue("$Username", TextBox1.Text.Trim());
    cmd.Parameters.AddWithValue("$_Password", TextBox2.Text.Trim());
    
    // 定义输出参数,指定类型和方向
    var outputParam = cmd.Parameters.Add("$UserId", MySqlDbType.Int32);
    outputParam.Direction = ParameterDirection.Output;
    
    try
    {
        con.Open();
        // 因为不需要读取结果集,用ExecuteNonQuery更高效
        cmd.ExecuteNonQuery();
        
        // 执行完成后才能读取输出参数的值
        userId = Convert.ToInt32(outputParam.Value);
        
        // 只有验证通过(userId不是-2/-3)时,再查询用户角色
        if (userId > 0)
        {
            using (var roleCmd = new MySqlCommand("SELECT RoleId FROM Users WHERE UserId = @UserId", con))
            {
                roleCmd.Parameters.AddWithValue("@UserId", userId);
                roles = roleCmd.ExecuteScalar()?.ToString() ?? string.Empty;
            }
        }
        
        switch (userId)
        {
            case -2:
                Label1.Text = "Username and/or password is incorrect.";
                break;
            case -3:
                Label1.Text = "Account does not exist.";
                break;
            default:
                // 创建Forms认证票据
                FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
                    1, 
                    TextBox1.Text, 
                    DateTime.Now, 
                    DateTime.Now.AddMinutes(2880), 
                    false, 
                    roles, 
                    FormsAuthentication.FormsCookiePath);
                
                string hash = FormsAuthentication.Encrypt(ticket);
                HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);
                
                if (ticket.IsPersistent)
                {
                    cookie.Expires = ticket.Expiration;
                }
                
                Response.Cookies.Add(cookie);
                Response.Redirect(FormsAuthentication.GetRedirectUrl(TextBox1.Text, false));
                break;
        }
    }
    catch (Exception ex)
    {
        // 可添加异常日志记录逻辑
        Label1.Text = $"An error occurred: {ex.Message}";
    }
    finally
    {
        // 确保数据库连接关闭,避免连接泄漏
        if (con.State == ConnectionState.Open)
        {
            con.Close();
        }
    }
}

关键注意点:

  • 输出参数读取时机:必须在执行ExecuteNonQuery(或关闭DataReader后)才能读取输出参数的值——DataReader未关闭时,输出参数的值还未从数据库端返回。
  • 避免多余结果集:原存储过程的SELECT *会生成额外结果集,导致C#端必须用ExecuteReader处理,改用SET赋值后用ExecuteNonQuery更简洁高效。
  • 异常与连接管理:用try-catch-finally确保无论是否出错,数据库连接都能正确关闭,防止连接泄漏。
  • 参数安全:已经使用参数化查询避免SQL注入,建议额外对输入参数做长度、格式验证。

内容的提问来源于stack exchange,提问作者Amit Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:44:23