.NET 6.0中获取可用SQL Server的替代方法(原方法失效)
.NET 6 替代 SqlDataSourceEnumerator.GetDataSources() 的解决方案
因为.NET 6及以后版本移除了System.Data.Sql.SqlDataSourceEnumerator,你可以通过**SQL Server管理对象(SMO)**实现相同功能——这也是原方法底层依赖的逻辑之一,且能返回你需要的所有字段。
步骤1:安装SMO NuGet包
在项目中安装官方维护的.NET 6兼容包:
Install-Package Microsoft.SqlServer.SqlManagementObjects # 或使用.NET CLI dotnet add package Microsoft.SqlServer.SqlManagementObjects
步骤2:实现枚举逻辑
下面的代码会枚举可用SQL Server实例,并映射到与原方法一致的字段结构:
using Microsoft.SqlServer.Management.Smo; using System; using System.Collections.Generic; using System.Linq; // 定义与原方法返回结构匹配的实体类 public class SqlServerInstanceInfo { public string Server { get; set; } public string Name { get; set; } public string Instance { get; set; } public string Version { get; set; } public bool IsLocal { get; set; } } public static class SqlServerEnumerator { public static List<SqlServerInstanceInfo> GetAvailableSqlServers() { var servers = SmoApplication.EnumAvailableSqlServers(false); var localMachineName = Environment.MachineName; return servers.Select(server => new SqlServerInstanceInfo { Server = server.Name.Split('\\')[0], Name = server.Name, Instance = server.Instance, Version = server.Version != null ? server.Version.ToString() : string.Empty, IsLocal = string.Equals(server.Name.Split('\\')[0], localMachineName, StringComparison.OrdinalIgnoreCase) }).ToList(); } }
关键说明
- 字段映射:
Server:提取实例名称中的机器名部分(比如DESKTOP-XXX\SQLEXPRESS中的DESKTOP-XXX)Name:完整的实例名称(机器名+实例名)Instance:实例名(默认实例为空)Version:SQL Server版本号(如15.0.2000.5)IsLocal:通过对比机器名判断是否为本地实例
- 依赖条件:目标机器需启用SQL Browser服务,防火墙需允许UDP 1434端口通信(SQL Browser用此端口响应探测)
- 权限:运行代码的进程需具备网络枚举权限,域环境下可能需额外配置
备选方案:手动UDP探测(无SMO依赖)
如果不想依赖SMO包,可手动实现UDP广播探测SQL Browser服务(逻辑与原方法一致),但需自行处理底层解析:
using System.Net; using System.Net.Sockets; using System.Text; using System.Collections.Generic; using System.Linq; public static List<SqlServerInstanceInfo> DiscoverSqlServersUdp() { var serverList = new List<SqlServerInstanceInfo>(); var udpClient = new UdpClient(); udpClient.EnableBroadcast = true; udpClient.ReceiveTimeout = 5000; var localMachineName = Environment.MachineName; // 发送SQL Browser探测包 byte[] requestBytes = Encoding.ASCII.GetBytes(""); udpClient.Send(requestBytes, requestBytes.Length, new IPEndPoint(IPAddress.Broadcast, 1434)); try { while (true) { IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); byte[] responseBytes = udpClient.Receive(ref remoteEndPoint); string response = Encoding.ASCII.GetString(responseBytes); // 解析SQL Browser响应格式 var props = response.Split(';') .Where(s => !string.IsNullOrEmpty(s) && s.Contains('=')) .ToDictionary(s => s.Split('=')[0], s => s.Split('=')[1]); if (props.TryGetValue("ServerName", out var serverName) && props.TryGetValue("InstanceName", out var instanceName)) { string fullName = string.IsNullOrEmpty(instanceName) ? serverName : $"{serverName}\\{instanceName}"; serverList.Add(new SqlServerInstanceInfo { Server = serverName, Name = fullName, Instance = instanceName, Version = props.TryGetValue("Version", out var v) ? v : string.Empty, IsLocal = string.Equals(serverName, localMachineName, StringComparison.OrdinalIgnoreCase) }); } } } catch (SocketException ex) when (ex.SocketErrorCode == SocketError.TimedOut) { // 超时表示无更多响应 } finally { udpClient.Close(); } return serverList.DistinctBy(s => s.Name).ToList(); }
注意:手动UDP方案需自行处理响应格式解析,实现复杂度更高,仅适合无法使用SMO的场景。
内容的提问来源于stack exchange,提问作者inejwstine
相关产品推荐
相关产品推荐

