【问题标题】:.Net Client Timeout.Net 客户端超时
【发布时间】:2012-03-28 22:31:41
【问题描述】:

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

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

超时。在获得一个之前经过的超时时间 来自池的连接...

如何解决?

【问题讨论】:

  • 增加连接超时时间。
  • 您确定连接到 SQL Server 的所有其他位置在完成后断开/关闭/释放连接吗?
  • 我的网络很小,从服务器接收到的信息很少。我真的不知道为什么会出现这个错误!
  • “和密码=@Password”。在某个地方,每次有人将明文密码作为 SQL 参数传递时,一只小猫就会死去:(
  • 尝试使用using 语句来处理您的IDisposable 对象。这将包括(至少)connectioncommanddataReader

标签: c# winforms sql-server-2008 timeout


【解决方案1】:

重构您的代码,使其看起来像这样。实施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();
}

【讨论】:

    【解决方案2】:

    如果你出现这种情况:

    • 泄漏连接(留给 GC 处理而不是处理它们)
    • 只是发生了太多事情,以至于池耗尽了

    第一个是最常见的,我预计它与您的错误处理过于复杂这一事实有很大关系。这很容易错过,而且很难发现你错过了它。显示的代码看起来不错,但最好对所有IDisposable 元素使用using 块,而不是finally。还;不要在显示消息框等模态内容时保持连接,除非您之后需要连接。坦率地说,干净地分离 UI 和数据访问代码可以带来很多好处,那么在数据库查询中间插入一个消息框没有诱惑

    但是!明确地说,我相信这段代码是其他一些占用连接的代码的受害者。查看您的其他数据访问代码以了解原因。

    【讨论】:

      【解决方案3】:

      您收到此异常的原因是您的连接池和应用程序中的“可用”连接数已用尽。

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

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

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

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-21
        • 2019-05-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多