我无法连接到 SQL Server 2017 (14.0.1000.169)本地数据库共享实例。
我在一台笔记本电脑上试过,它以前有一些 SQL Server Express 和我都卸载的东西。并且还在新的 Win10 虚拟机上。
两者总是有相同的错误:
Sqlcmd:错误:Microsoft ODBC Driver 17 for SQL Server:命名管道提供程序:无法打开与 SQL Server 2的连接。.
Sqlcmd:错误:Microsoft ODBC Driver 17 for SQL Server:登录超时已过期。
Sqlcmd:错误:Microsoft ODBC Driver 17 for SQL Server:建立与 SQL Server 的连接时发生与网络相关或特定于实例的错误。服务器未找到或无法访问。检查实例名称是否正确以及 SQL Server 是否配置为允许远程连接。有关详细信息,请参阅 SQL Server 联机丛书。
此错误来自,SQLCMD
但我也尝试过使用 SSMS 和 Visual Studio 连接字符串。
我尝试与实例的所有者联系,但不能。还尝试使用具有系统管理员权限的 SQL 登录,但不能。
我只能连接管道名称。
我还尝试了以下所有方法:
- 为什么我无法连接到 SQL Server 2012 LocalDB 共享实例?在堆栈溢出
- SQL 2016 sp1 SQLLocalDB 版本错误,“Windows API 调用“RegGetValueW”返回错误代码:0。” 在 MSDN 论坛上
为什么我无法连接?
此问题通过以下方式解决:
KB5003342-修复:SQL Server Express LocalDB 无法启动或连接到 SQL Server Express LocalDB 2019 或 2017 的共享实例
演示:
似乎是 LocalDb v2017 及更高版本中的错误。我测试了所有可用的版本,从 v2012 SP4 开始。在 v2016 SP2 之前(包括 v2016 SP2),友好共享名称
"(localdb)\.\SHAREDNAME"
在连接请求中被接受。使用 v2017 或更高版本时,请求始终会导致“未找到实例”错误。我还观察到查询所有已安装的 LocalDb 版本
sqllocaldb.exe v
会导致出现 v2016 及更高版本的错误消息:不确定此行为是否可能与原始问题有关。
应用问题中链接的注册表修复解决了版本查询。
经过一番挖掘,我想我可能已经找到了连接失败的原因。在本地计算机上安装最高 v2016的 SQLLocalDb 时,共享功能的工作方式如下:
在注册表中,会在 中创建一个新键
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server Local DB\Shared Instances\{SharedName}
。此键包含一个字符串 valueInstanceName
,它存储管道名称,如以下屏幕截图所示:当相应的实例启动时,它总是选择这个管道名称。该名称保持不变,即当实例重新启动时,管道名称被重用。
安装 LocalDb v2017 或更高版本时会破坏此逻辑:当启动具有共享名称的实例时,将忽略注册表中的管道名称。相反,通过查询实例时会出现完全不同的管道名称
sqllocaldb i {instance}
。这可能也是无法建立连接的原因,因为管道名称不匹配。编辑注册表值以匹配实际管道名称可以解决问题,但仅在重新启动实例之前。
正如 Aurora 所建议的那样,这是 LocalDB >= 2017 中的一个错误,微软似乎并不关心它。原因可能是因为 LocalDb 不应该在生产环境中使用。建议的解决方法很好,但需要手动完成。
要在您的软件中解决此问题,您可以实施以下解决方法:
sqllocaldb i {your_shared_instance_name}
在单独的进程中运行并获取结果)。此外,此时记录命名管道(格式:np:\\.\pipe\LOCALDB#AC471EDC\tsql\query
- 提取管道 id 值使用此正则表达式:#(.*?)\\
-> 如果匹配使用match.Groups[1].Value
)SOFTWARE\Microsoft\Microsoft SQL Server Local DB\Shared Instances\\{your_shared_instance_name}
InstanceName
(C# 示例)
获取密钥:
using var myKey = Registry.LocalMachine.OpenSubKey($"SOFTWARE\Microsoft\Microsoft SQL Server Local DB\Shared Instances\\{instanceName}", true);
如果它与管道 ID 不同:
myKey.SetValue("InstanceName", $"LOCALDB#{pipeId}", RegistryValueKind.String);
结论
现在一切都应该工作了。每 30 秒左右检查一次,以确保在数据库进程失败/系统重新启动/等情况下恢复正常。抱歉,但这似乎是 2017 年升级后保持 LocalDb 存活的唯一解决方案。另一种解决方案是迁移到 SQL Express 服务器。
这只是代码的一个示例,但希望您能理解。如果没有,请发表评论,我会尽力帮助您。我为此挣扎了一会儿,但它最终以 LocalDb 2014/2016 的形式运行,没有任何问题。