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

Parameters.AddWithValue使用运算符报username非空错误解决办法

问题原因

你遇到的username must be not null报错和Parameters.AddWithValue使用运算符无关,核心是代码存在3个明显错误:

  • SQL语法逻辑错误:你写的UNION查询仅在第二个admin_accounts表查询后加了where过滤,前半段查询accounts表时没有任何筛选条件,会把accounts表全量数据都查出来,完全没有做用户名/邮箱的匹配。
  • 空值未处理:你注释掉了username的入参空校验,当前端仅传邮箱参数做登录时,username变量为null,你直接把null值传入AddWithValue,后续设置Session时又直接使用这个null的username变量,就会触发非空报错。
  • 校验逻辑顺序错误:你把密码校验放在SqlDataReader的遍历循环里,只要读到的第一条记录密码不匹配就直接返回wrong_password,哪怕后续存在真正匹配的账号也不会继续校验,逻辑完全不成立。
正确实现方式

Parameters.AddWithValue本身只负责给SQL参数传值,不存在“在其中使用运算符”的用法,运算符需要写在SQL语句里,你只需要按以下步骤修正代码即可:

  • 修正SQL语句,给两个关联表的查询都加上相同的用户名/邮箱匹配条件,使用UNION ALL替代UNION提升查询性能
  • 给参数传值时处理空值,入参为null时传入DBNull.Value,避免SQL参数异常
  • 调整校验逻辑,先确认查到匹配用户名/邮箱的账号记录,再做密码哈希比对、账号状态校验
  • 写入Session时使用数据库查询返回的username字段值,不要直接使用前端传入的参数,避免空值问题
  • 移除冗余的手动con.Close()调用和重复的using(con)嵌套,外层using代码块会自动释放数据库连接资源
修正后的核心代码
public JsonResult Loginzxc(string email, string username, string password)
{
    // 基础入参校验
    if (string.IsNullOrEmpty(password))
    {
        return Json("wrong_password");
    }
    if (string.IsNullOrEmpty(username) && string.IsNullOrEmpty(email))
    {
        return Json("wrong_username");
    }

    using (SqlConnection con = new SqlConnection(constring))
    {
        string access = @"select reg_no, username, status, user_type, password from accounts 
                        where (@user is not null and username = @user) or (@email is not null and email = @email)
                        union all
                        select reg_no, username, status, user_type, password from admin_accounts 
                        where (@user is not null and username = @user) or (@email is not null and email = @email)";

        string pass1 = ComputeSha256Hash(password);

        using (SqlCommand com = new SqlCommand(access, con))
        {
            // 处理参数空值
            com.Parameters.AddWithValue("@user", string.IsNullOrEmpty(username) ? (object)DBNull.Value : username);
            com.Parameters.AddWithValue("@email", string.IsNullOrEmpty(email) ? (object)DBNull.Value : email);
            com.CommandTimeout = 60;

            con.Open();
            using (SqlDataReader rreader = com.ExecuteReader())
            {
                if (rreader.HasRows)
                {
                    while (rreader.Read())
                    {
                        string pass2 = rreader["password"].ToString();
                        // 密码不匹配跳过当前记录,继续查找匹配账号
                        if (pass2 != pass1)
                        {
                            continue;
                        }

                        string status = rreader["status"].ToString();
                        string user_type = rreader["user_type"].ToString();
                        string reg_no = rreader["reg_no"].ToString();
                        // 使用数据库查询返回的用户名,不直接用前端传参
                        string dbUsername = rreader["username"].ToString();

                        if (user_type == "0")
                        {
                            user_type = "ADMIN";
                        }
                        else if (user_type == "1")
                        {
                            user_type = "MEMBER";
                        }

                        if (status == "INACTIVE")
                        {
                            return Json("INACTIVE");
                        }
                        else if (status == "BLOCKED")
                        {
                            return Json("BLOCKED");
                        }
                        else if (status == "ACTIVE")
                        {
                            HttpContext.Session.SetString("username", dbUsername);
                            HttpContext.Session.SetString("reg_no", reg_no);
                            HttpContext.Session.SetString("user_type", user_type);

                            if (user_type == "ADMIN")
                            {
                                return Json(new { redirectUrl = Url.Action("Index", "Admin", new { id = "DSA" + reg_no }) });
                            }
                            else if (user_type == "MEMBER")
                            {
                                return Json(new { redirectUrl = Url.Action("Index", "Home", new { id = "DSA" + reg_no }) });
                            }
                        }
                        else
                        {
                            return Json("error");
                        }
                    }
                    // 所有匹配账号遍历完成,密码均不匹配
                    return Json("wrong_password");
                }
            }
            ViewBag.notfound = "login";
            return Json("no record");
        }
    }
}

生产环境建议显式指定SqlParameter的类型和长度,不要完全依赖AddWithValue的自动类型推断,避免出现执行计划缓存复用差、隐式类型转换导致索引失效的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 20:18:14