有没有人能注意到以下功能可能出现的问题:
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();抛出异常。
由于
答案 0 :(得分:5)
表中很可能没有包含该用户/密码的行。 ExecuteScalar的文档说如果结果集为空则返回null,并且不能将null转换为int。
答案 1 :(得分: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 :(得分:1)
如果在数据库中找不到提供的凭据,标量是否可能为空?
答案 3 :(得分:0)
不确定,但您可能需要“@”作为参数名称:
...AddWithValue("@username", username);
答案 4 :(得分:0)
我在使用SqlCE时遇到了同样的问题。我找到的解决方案(在我开始输入密码正确...>。>之后),首先将ExecuteScalar结果作为对象收集,然后转换为第二个。 Litterally,使用
Object o = cmd.ExecuteScalar();
int id = Convert.ToInt32(o);
而不是
int id = (int) cmd.ExecuteScalar();
是工作和崩溃之间的区别。我不知道为什么会这样......
答案 5 :(得分:0)
我没有看到任何hashbytes功能,但在这里:
如果在后端SQL服务器上使用hashbytes
函数,则将密码输入转换为二进制数组。
Hashbytes返回varbinary。因此,如果您传递空终止符,则哈希值不会相同。就像在SQL hashbytes('SHA2_512,'stuff')
中一样,就像哈希',' t',直到' f'。没有' \ 0'在末尾。但是如果你在sqlcommand对象中将其参数化为字符串,它将添加' \ 0'最后,SQL将计算零。因此,如果使用Encoding
类转换为二进制数组,则参数将只是不带空终止符的字符串。
我遇到了类似的问题,我以这种方式解决了使用addwithvalue
及其值为二进制的问题。
但是,你知道executecalar返回一个对象。如果查询返回零行,则该对象将为NULL,并且您无法将NULL对象转换或转换为任何对象。所以在if语句中说"如果returnsobject == null,那么你不会被authed。别的...."