.Net客户端超时

时间:2012-03-12 14:04:43

标签: 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=@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();
    }
}

一切正常,但有时我会收到以下错误:

  

超时已过期。获得a之前经过的超时时间   从泳池连接...

如何解决这个问题?

3 个答案:

答案 0 :(得分:3)

您获得此异常的原因是您的连接池耗尽以及应用程序中“可用”连接的数量。

每次打开连接时,如果可能,都会从连接池中拔出一个连接,否则会创建一个新连接。

但是,为了防止连接的误用,限制为100(我认为这是可配置的),并且如果您尝试使用超过100个并发连接,代码将创建新的那些,而是坐下来等待一个人返回池中,在这种情况下,如果它太长,你会得到一个超时。

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

  

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

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

除此之外,我会浏览整个应用程序并确保其他地方没有任何连接泄漏。

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

答案 1 :(得分:1)

如果您要么:

  • 泄漏连接(留给他们处理GC而不是处理它们)
  • 发生了太多事情,以至于游泳池已经用尽

第一个是最常见的,我期待它与你的错误处理过度复杂这一事实有很大关系。这很容易错过,很难发现你错过了它。显示的代码看起来不错,但是对于所有using元素而不是IDisposable使用finally块会更好。也;在显示消息框等模态内容时不要保持连接,除非之后需要连接。坦率地说,通过干净地分离UI和数据访问代码可以获得很多好处,然后在数据库查询的中间有一个消息框 not temptation

然而!明确地说,我相信这段代码是其他一些代码的受害者。请查看其他数据访问代码,了解其原因。

答案 2 :(得分:0)

重构你的代码看起来像这样。实施using块。这里的其他答案非常重要,请务必理解它们。

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();
}