C# 使用SqlReader时发生异常

C# 使用SqlReader时发生异常,c#,database,ado.net,C#,Database,Ado.net,我尝试从多个线程调用此方法,试图从同一字符串获取ID。我总是在创建SqlDataReader的那一行遇到这个异常: 已存在与此命令关联的打开的DataReader,该命令 必须先关闭 我不知道问题出在哪里。我使用的是lock()语句,所以我只使用一次命令,然后处理它。对数据库编程来说有点陌生,所以我不知道我的错误在哪里 谢谢 public int UsernameGetID(string username) { using (var command = new SqlCommand("S

我尝试从多个线程调用此方法,试图从同一字符串获取ID。我总是在创建SqlDataReader的那一行遇到这个异常:

已存在与此命令关联的打开的DataReader,该命令 必须先关闭

我不知道问题出在哪里。我使用的是lock()语句,所以我只使用一次命令,然后处理它。对数据库编程来说有点陌生,所以我不知道我的错误在哪里

谢谢

public int UsernameGetID(string username)
{
    using (var command = new SqlCommand("SELECT user_id FROM " + ServerConstants.Database.TableUserInformation + " WHERE username = @Username", connection))
    {
        lock (command)
        {
            SqlParameter param = new SqlParameter("@Username", SqlDbType.VarChar, username.Length);
            param.Value = username;
            command.Parameters.Add(param);
            using (SqlDataReader reader = command.ExecuteReader())
            {
                if (reader.Read())
                {
                    return (int)reader[0];
                }
                else
                {
                    // username doesn't exists
                    return 0;
                }
            }
        }
    }
}

锁定
命令
是没有意义的,因为您正在方法中创建一个新命令-没有其他代码可以锁定它

但是,您正在共享多个命令之间的连接。不要这样做-在每次调用中创建一个新的
SqlConnection
(同样,在
中使用
语句)。不要担心效率方面——连接池将负责“真正的”网络连接

所以你想要:

using (var connection = new SqlConnection(...))
using (var command = new SqlCommand(..., connection))
{
    connection.Open();
    ...
    using (var reader = command.ExecuteReader())
    {
        return reader.Read() ? (int) reader[0] : 0;
    }
}

如果您不共享
connection
变量,而是在
UsernameGetID
方法本身中创建连接,该怎么办?您使用的是以前或其他SQLDataReader中打开的连接,这不会影响性能吗?我只想使用一个连接,因为我不想每次从数据库中获取内容时都创建一个连接实例。我只有一个连接,所有的命令都在上面完成。这样做不好吗?您是否为其他读者使用相同的
连接?如果是,您可以尝试添加
MultipleActiveResultSets=true到连接字符串的末尾。或者只是创建一个新的
SqlConnection
@Pacha:是的,它是。正如您所发现的,它很容易出错。连接池将为您处理此问题-它不会每次都创建新的网络连接。