SqlClient连接远程SQL Server时为何尝试选用HTTP Provider?
问题场景
我在.NET Framework 4.8的WPF应用中使用Microsoft.EntityFrameworkCore 3.1.30访问远程SQL Server 2016 Express,遇到以下错误:
Microsoft.Data.SqlClient.SqlException (0x80131904): 建立与SQL Server的连接时出现与网络相关或特定于实例的错误。找不到服务器或无法访问服务器。验证实例名称是否正确,以及SQL Server是否配置为允许远程连接。(provider: HTTP Provider, error: 0 - )
我的连接字符串指定了IP地址(非命名实例)且设置Trust server certificates = True,但只有手动在IP地址前加上tcp:协议前缀才能成功连接。想知道为什么SqlClient会自动尝试选用HTTP Provider?
原因分析
客户端协议优先级配置问题
本地SqlClient的协议尝试顺序可能被配置为HTTP优先于TCP。当连接字符串未明确指定协议时,SqlClient会按预设的协议顺序依次尝试连接,刚好先触发了HTTP协议的连接逻辑,而目标服务器未开启HTTP远程连接支持,因此抛出错误。连接字符串的隐式解析逻辑
针对非命名实例的IP连接,SqlClient的默认解析逻辑在某些特殊环境(如本地存在自定义SQL配置、网络环境存在代理或路由干扰)下,可能误判为需要尝试HTTP协议。显式指定tcp:前缀后,会强制SqlClient跳过其他协议探测,直接使用TCP连接。特定版本SqlClient的行为特性
你使用的EF Core 3.1.30对应的Microsoft.Data.SqlClient版本,在协议探测逻辑上存在特定场景下的行为:当未指定协议时,会包含HTTP在内的多种协议进行尝试,且TCP未被设置为最高优先级。
解决建议
- 直接在连接字符串的IP地址前添加
tcp:前缀,强制SqlClient使用TCP协议,彻底规避协议探测带来的异常。 - 通过
SQL Server Configuration Manager检查本地SQL Server客户端的协议顺序,将TCP/IP协议调整到HTTP之前,确保优先尝试TCP连接。
内容的提问来源于stack exchange,提问作者Genesio

