【问题标题】:SQLCommand.ExecuteScalar() - why it throws a System.NullReferenceException?SQLCommand.ExecuteScalar() - 为什么它会抛出 System.NullReferenceException?
【发布时间】:2009-03-24 02:50:54
【问题描述】:

谁能注意到以下函数可能有什么问题:

public string Login(string username, string password)
    {
        string result = "";
        string select = "SELECT user_id FROM [user] WHERE username = @username AND password = @password";
        SqlConnection conn = new SqlConnection(connectionString);
        SqlCommand cmd = new SqlCommand(select, conn);
        cmd.Parameters.AddWithValue("username", username);
        cmd.Parameters.AddWithValue("password", password);
        int userID = 0;
        try
        {
            conn.Open();
            userID = (int)cmd.ExecuteScalar();
            if(userID > 0)
            {
                result = addSession(userID);
            }
        }
        catch(Exception ex)
        {
            string sDummy = ex.ToString();
        }
        return result;
    }

不知道为什么行`userID = (int)cmd.ExecuteScalar();抛出异常。

谢谢

【问题讨论】:

  • 您应该发布完整的异常,包括任何 InnerException。
  • 为避免其他问题,请将“密码”字段括在方括号中,因为这也是保留字。

标签: .net exception sqlcommand


【解决方案1】:

你应该考虑修改这段代码:

try
{
    conn.Open();
    userID = (int)cmd.ExecuteScalar();
    if(userID > 0)
    {
        result = addSession(userID);
    }
 }
 catch(Exception ex)
 {
    string sDummy = ex.ToString();

 }
 finally // add this to ensure the connection is closed!
 {
     if (conn != null)
       conn.Close();
 }

【讨论】:

    【解决方案2】:

    表中很可能没有具有该用户/密码的行。 ExecuteScalar 的文档说,如果结果集为空,它会返回 null,并且您不能将 null 转换为 int。

    【讨论】:

    • 调用 ExecuteScalar 时的良好做法是确保查询返回结果。查询可以更改为:SELECT ISNULL(MAX(user_id),-1) FROM [USER] ...
    【解决方案3】:

    如果在数据库中找不到提供的凭据,标量是否可能为空?

    【讨论】:

      【解决方案4】:

      不确定,但您可能需要“@”作为参数名称:

      ...AddWithValue("@username", username);
      

      【讨论】:

        【解决方案5】:

        我在使用 SqlCE 时遇到了同样的问题。我找到的解决方案(在我开始正确输入密码之后... >.> )是首先将 ExecuteScalar 结果作为对象收集,然后再进行转换。从字面上看,使用

        Object o = cmd.ExecuteScalar(); 
        int id = Convert.ToInt32(o); 
        

        而不是

        int id = (int) cmd.ExecuteScalar(); 
        

        是工作和崩溃之间的区别。我不知道为什么会这样......

        【讨论】:

          【解决方案6】:

          我没有看到任何 hashbytes 函数,但它是这样的:

          如果您在后端 SQL 服务器上使用hashbytes 函数,则将密码输入转换为二进制数组。 Hashbytes 返回 varbinary。因此,如果您传递空终止符,则哈希将不一样。就像在 SQL hashbytes('SHA2_512,'stuff') 中一样,就像散列's','t',直到'f'。最后没有'\0'。但是,如果您在 sqlcommand 对象中参数化为字符串,它将在末尾添加 '\0' 并且 SQL 将计算该零。因此,如果您将使用 Encoding 类转换为二进制数组,则参数将只是没有空终止符的字符串。 我遇到了类似的问题,我以这种方式解决了使用addwithvalue 及其二进制值。

          但是,您知道 executescalar 返回一个对象。如果查询返回零行,则该对象将为 NULL,并且您不能将 NULL 对象强制转换或转换为任何对象。所以在 if 语句中说“如果返回对象 == null 那么你没有经过身份验证。否则......”

          【讨论】:

            猜你喜欢
            • 2016-08-27
            • 1970-01-01
            • 2021-12-20
            • 2021-03-05
            • 2021-03-19
            • 2023-03-14
            • 1970-01-01
            • 1970-01-01
            • 2021-04-09
            相关资源
            最近更新 更多