C# .Net客户端超时

C# .Net客户端超时,c#,winforms,sql-server-2008,timeout,C#,Winforms,Sql Server 2008,Timeout,在我的Windows应用程序中,我尝试使用以下代码连接到SQL Server 2008: SqlConnection connection = new SqlConnection(Properties.Settings.Default.KargarBandarConnectionString); SqlCommand command = new SqlCommand("Select IsAdmin from Users where UserName=@UserName And Password=

在我的Windows应用程序中,我尝试使用以下代码连接到SQL Server 2008:

SqlConnection connection = new SqlConnection(Properties.Settings.Default.KargarBandarConnectionString);
SqlCommand command = new SqlCommand("Select IsAdmin from Users where UserName=@UserName And Password=@Password", connection);
SqlDataReader dataReader = null;

command.Parameters.AddWithValue("@UserName", UserNameTextBox.Text.Trim());
command.Parameters.AddWithValue("@Password", PasswordTextBox.Text);
try
{
    connection.Open();
    dataReader = command.ExecuteReader();

    if (dataReader.HasRows)
    {
        while (dataReader.Read())
        {
            IsAdmin = dataReader.GetBoolean(0);
        }
        this.DialogResult = DialogResult.OK;
    }
    else
    {
       FMessageBox.ShowWarning("error");
        UserNameTextBox.Focus();
    }
}
catch (Exception ex)
{
    if (progressForm != null)
        progressForm.Close();

    FMessageBox.ShowError(ex.Message);
}
finally
{
    if (dataReader != null)
    {
        dataReader.Close();
        dataReader.Dispose();
    }
    if (connection != null)
    {
        connection.Close();
        connection.Dispose();
    }
}
一切正常,但有时会出现以下错误:

超时已过期。获取数据之前经过的超时时间 来自池的连接


如何解决此问题?

出现此异常的原因是您已耗尽了连接池以及应用程序中的“可用”连接数

每次打开连接时,都会从连接池中拉出一个连接(如果可能),或者创建一个新连接(如果不可能)

但是,为了防止连接的快速使用,存在100个限制(我认为这是可配置的),如果您尝试同时使用100个以上的连接,代码将不会创建新的连接,而是坐下来等待一个连接返回到池中,在这种情况下,如果它太长,您将得到一个超时

因此,对于您展示的特定代码示例,我将:

在向用户显示错误消息之前,请关闭连接

但是,除非100个用户同时看到错误消息并将其留在那里,否则您显示的代码不太可能是导致此问题的原因

除此之外,我会检查整个应用程序,确保您在其他地方没有任何连接泄漏


即使问题在其他地方,这种特殊类型的异常也可能发生在一个地方。示例:报表每次运行时都会泄漏打开的连接,并且您成功运行了100次,然后有人尝试登录,登录表单中出现异常。

出现此异常的原因是您耗尽了连接池和应用程序中的“可用”连接数

每次打开连接时,都会从连接池中拉出一个连接(如果可能),或者创建一个新连接(如果不可能)

但是,为了防止连接的快速使用,存在100个限制(我认为这是可配置的),如果您尝试同时使用100个以上的连接,代码将不会创建新的连接,而是坐下来等待一个连接返回到池中,在这种情况下,如果它太长,您将得到一个超时

因此,对于您展示的特定代码示例,我将:

在向用户显示错误消息之前,请关闭连接

但是,除非100个用户同时看到错误消息并将其留在那里,否则您显示的代码不太可能是导致此问题的原因

除此之外,我会检查整个应用程序,确保您在其他地方没有任何连接泄漏


即使问题在其他地方,这种特殊类型的异常也可能发生在一个地方。示例:报表每次运行时都会泄漏打开的连接,并且您成功运行了100次,然后有人尝试登录,登录表单中会出现异常。

如果您:

  • 泄漏连接(留给GC处理,而不是处理)
  • 只是发生了太多的事情,以至于游泳池已经耗尽
第一种是最常见的,我认为这与错误处理过于复杂这一事实有很大关系。这使得你很容易错过,也很难发现你错过了它。显示的代码看起来不错,但最好对所有
IDisposable
元素使用
using
块,而不是
finally
。也;在显示消息框之类的模式时不要保持连接,除非之后需要连接。坦率地说,这里可以通过干净地分离UI和数据访问代码来获得很多好处,那么在数据库查询中间不存在将消息框粘在一起的诱惑。
然而!明确地说,我相信这段代码是占用连接的其他代码的受害者。查看您的其他数据访问代码以了解原因。

如果您:

  • 泄漏连接(留给GC处理,而不是处理)
  • 只是发生了太多的事情,以至于游泳池已经耗尽
第一种是最常见的,我认为这与错误处理过于复杂这一事实有很大关系。这使得你很容易错过,也很难发现你错过了它。显示的代码看起来不错,但最好对所有
IDisposable
元素使用
using
块,而不是
finally
。也;在显示消息框之类的模式时不要保持连接,除非之后需要连接。坦率地说,这里可以通过干净地分离UI和数据访问代码来获得很多好处,那么在数据库查询中间不存在将消息框粘在一起的诱惑。
然而!明确地说,我相信这段代码是占用连接的其他代码的受害者。请查看您的其他数据访问代码以了解原因。

重构代码,使其看起来像这样。使用块执行
。这里的其他答案非常重要,请务必理解它们

bool res=false;
try
{
    using(var connection = new SqlConnection(Properties.Settings.Default.KargarBandarConnectionString))
    using(var cmd = conn.CreateCommand())
    {       
        cmd.commandText = "Select IsAdmin from Users where UserName=@UserName And HashedAndSaltedPassword=@PwdHash";
        cmd.Parameters.AddWithValue("@UserName", UserNameTextBox.Text.Trim());
        cmd.Parameters.AddWithValue("@PwdHash", SaltAndHash(PasswordTextBox.Text));     
        connection.Open();
        var result = cmd.ExecuteScalar();
        if (result!=null)
        {
            res=bool.Parse(result);       
            this.DialogResult = DialogResult.OK;
        }   
    }
}
catch (Exception ex)
{   
    if (progressForm != null){progressForm.Close();}
    FMessageBox.ShowError(ex.Message);
}

if(res==false)
{
    FMessageBox.ShowWarning("error");
    UserNameTextBox.Focus();
}

重构代码,使其看起来像这样。使用
块执行
。这里的其他答案非常重要,请务必理解它们

bool res=false;
try
{
    using(var connection = new SqlConnection(Properties.Settings.Default.KargarBandarConnectionString))
    using(var cmd = conn.CreateCommand())
    {       
        cmd.commandText = "Select IsAdmin from Users where UserName=@UserName And HashedAndSaltedPassword=@PwdHash";
        cmd.Parameters.AddWithValue("@UserName", UserNameTextBox.Text.Trim());
        cmd.Parameters.AddWithValue("@PwdHash", SaltAndHash(PasswordTextBox.Text));     
        connection.Open();
        var result = cmd.ExecuteScalar();
        if (result!=null)
        {
            res=bool.Parse(result);       
            this.DialogResult = DialogResult.OK;
        }   
    }
}
catch (Exception ex)
{   
    if (progressForm != null){progressForm.Close();}
    FMessageBox.ShowError(ex.Message);
}

if(res==false)
{
    FMessageBox.ShowWarning("error");
    UserNameTextBox.Focus();
}

增加您的连接超时时间。是否确定在您连接到SQL Server的其他每个位置都断开/关闭/处置连接?我的网络很小,从服务器接收到的信息很少。我真的不知道为什么我会犯这个错误!“和密码=@Password”。在某个地方,每当有人将明文密码作为SQL参数传递时,一只小猫就会死去:(尝试使用
using
语句处理
IDisposable的处置