在预登录握手期间发生错误。

12

在标记为重复之前请完整阅读。

在我调试的项目中,我收到一个SqlException,内容如下:

附加信息:与服务器成功建立连接,但在预登录握手期间发生错误。(提供程序:SSL 提供程序,错误:0 - 等待操作已超时。)

这发生在一个调试会话中,在此之前的会话只有几秒钟之前执行,并且没有问题。自从出现初始异常以来,我无法在此项目中连接到数据库服务器。该异常在SqlConnection.Open()方法调用上抛出。

背景

这不是我第一次遇到这个问题了。以前我曾为此挣扎了两周,最终发起了一个微软支持票据。在那种情况下,问题最终被解决了,原来是连接字符串上的ApplicationName属性太长(我们使用了完全限定的程序集名称),将其缩短缓解了问题。

这一次,有以下情况:

  • 没有提供ApplicationName值
  • WinSocks处于默认状态
  • 杀毒软件(ESET)已被禁用,也不是问题。
  • 在工作和非工作调试会话之间未安装任何内容

最后,我突发奇想创建了一个新项目,其唯一目的是连接到同一SQL服务器。我将连接字符串从不工作的项目复制到新项目中,它就可以连接了。是否存在某种每个项目的连接缓存?某些在Clean>Rebuild和Visual Studio和Windows重启后仍然存在的东西?

相关代码

    public SqlConnection OpenSqlConnection(string connectionString)
    {
        var conn = new SqlConnection(connectionString);
        conn.Open();
        _connectionString = connectionString;
        var sb = new SqlConnectionStringBuilder(_connectionString);
        _server = sb.DataSource;
        _database = sb.InitialCatalog;
        return conn;
    }

传递的连接字符串是在应用程序中的另一个 SqlConnectionStringBuilder 输出的。该连接字符串类似于:"Data Source=SERVER;Initial Catalog=DATABASE;Integrated Security=True;Connect Timeout=60"


1
@CodeWarrior,能否检查一下目标 Sql Server 当前有多少个活动连接?我相信这些信息可以在 sys.connections 中找到。如果你在 Sql Server 中看到了该机器的 spid,请终止该 spid,然后再尝试连接。 - loneshark99
1
应该在sys.processes中使用kill spid命令来终止连接。当您完成连接时,是否关闭连接,例如:using(var connection = new SqlConnection()) { }? - loneshark99
你已经删除了.NET临时文件吗? - Ross Bush
我应该在哪里找到它们?我假设它们与在清理时被删除的构建文件夹是分开的? - CodeWarrior
每当出现异常情况时,我总是会清理临时文件。偶尔这么做会解决问题,但我猜测你的问题与网络相关。听起来好像远程连接和/或身份验证方面发生了变化。你尝试过使用Integrated Security=false连接吗?临时文件 --> C:\Windows\Microsoft.NET\Framework<64><DOT_NET_VERSION>\Temporary ASP.NET Files。 - Ross Bush
显示剩余15条评论
4个回答

3

对于我来说起作用的是增加连接字符串中的超时时间,因为通过 VPN 连接时建立连接需要很长时间。您可以通过添加 ;connection timeout = value 来实现此操作。

当我在 VPN 上时,尝试连接到 SQL Server 的应用程序也遇到了相同的错误。

默认情况下,超时时间设置为15秒。

看起来您已经有了60秒,也许您只需要更多时间...

希望对您有所帮助!


这对我来说解决了问题,即使在一个完全不相关的应用/上下文中。当我将该字段留空时,它会在15秒后出错。当我将其更改为60秒(也就是1分钟)时,它立即连接! - Zach Mierzejewski

2
尝试在连接字符串中明确添加 Application Name=MyAppName; 。来自程序集名称的自动生成值可能会超过某些限制。
检查网络设置,例如明确限制帧大小。如果SQL Server运行在另一台机器上,请重新启动路由器。
尝试添加 Pooling=False; 到连接字符串,并检查是否解决了应用程序重新启动时重复连接的问题。

应用名称属性的添加没有任何影响。网络设置没有改变(回想一下,在一个调试会话和下一个调试会话之间发生了这个问题,最多一分钟的时间段,期间我所做的只是点击VS的停止按钮和开始/调试按钮)。添加Pooling=false也没有任何效果。 - CodeWarrior
好的。您能否尝试使用登录名和密码连接,而不是集成安全性?数据源=服务器是否通过IP或名称标识?如果是名称,则是否在本地主机文件中? - Y.B.
通过 SQL 认证连接也出现了问题。数据源是按主机名设置的,而主机名在 HOSTS 中。通过 IP 地址连接也出现了问题。请记住,错误消息指出已连接到数据库,并且在预登录握手期间发生了错误。在这些情况下,与服务器的网络连接 不应该 成为问题,因为它表示已成功连接到服务器。 - CodeWarrior
1
额,谢谢,但我宁愿不要因为没有解决问题的答案而获得声望点数。你是放弃了还是找到了解决方案?根据问题投票,相当多的成员(包括我在内)会感激你分享解决方案。 - Y.B.
我想到了另一件需要检查的事情:在“配置属性”->“调试”中,展示问题的项目是否已激活“SQL Server调试”?如果在其他项目配置中运行,问题是否仍然存在? - Y.B.

1
这个问题可能与中间的防火墙进行SSL检查有关。建议您尝试使用另一个没有进行SSL检查的连接,或者请求您的防火墙管理员为您连接的源和/或目标创建豁免。祝好!

0

所以这个问题一直困扰着我,看起来是由于我的家庭网络(我是远程开发人员)和通过VPN访问的工作网络之间的延迟引起的。我对工作网络上的服务器的平均ping时间为100毫秒。

真正奇怪的是,连接字符串在几个月内都没有问题,然后突然停止了。当时,应用程序名称的值类似于Application Name =“MyProgram.DAL. Culture=en, PublicKeyToken=1a1a1a1a1a1a1a1a, Version=1.0.0.0”。换句话说,是一个完全限定的程序集名称。最终,我将其更改为缩短的“MyProgram.DAL”类型名称,然后它又可以正常工作了。

几个月后,我再次遇到了这个问题。我碰巧发现,如果我只是吞下异常并等待几个时钟周期,一切都会很好。即使应用程序报告失败,它也会愉快地使用连接。因此,我将方法更改为以下内容:

    public SqlConnection OpenSqlConnection(string connectionString)
    {
        var conn = new SqlConnection(connectionString);
        var retries = 10;
        while (conn.State != ConnectionState.Open && retries > 0)
        {
            try
            {
                conn.Open();
            }
            catch (Exception)
            {

            }
            Thread.Sleep(500);
            retries--;
        }

        _connectionString = connectionString;
        var sb = new SqlConnectionStringBuilder(_connectionString);
        _server = sb.DataSource;
        _database = sb.InitialCatalog;
        return conn;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接