首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

C# 獲取可見 SQL Server 實例與數據庫:SQLDMO 方案與 ODBC 底層 API 方案雙軌實現

     編輯:關於SqlServer

方案一:SQLDMO(COM 組件,需引用 Microsoft SQLDMO Object Library)

// 1. 獲取網絡可見 SQL Server 列表
List<string> servers = new List<string>();
SQLDMO.Application sqlApp = new SQLDMO.ApplicationClass();
SQLDMO.NameList sqlServers = sqlApp.ListAvailableSQLServers();
for (int i = 1; i <= sqlServers.Count; i++) {  // SQLDMO 集合 1-based
  object srv = sqlServers.Item(i);
  if (srv != null) servers.Add(srv.ToString());
}

// 2. 連接指定服務器獲取數據庫列表
List<string> databases = new List<string>();
foreach (string srvName in servers) {
  SQLDMO.SQLServer srv = new SQLDMO.SQLServerClass();
  srv.Connect(srvName, "sa", "123");  // 生產環境請用集成認證或配置文件
  foreach (SQLDMO.Database db in srv.Databases) {
    if (db.Name != null) databases.Add(db.Name);
  }
  srv.DisConnect();
}

// 3. 獲取存儲過程/表/視圖
SQLDMO.SQLServer srv2 = new SQLDMO.SQLServerClass();
srv2.Connect(cboServers.SelectedItem.ToString(), txtUser.Text, txtPassWord.Text);
for (int i = 1; i <= srv2.Databases.Count; i++) {
  if (srv2.Databases.Item(i, "dbo").Name == cboDatabase.SelectedItem.ToString()) {
    SQLDMO._Database db = srv2.Databases.Item(i, "dbo");
    lstObjects.Items.Clear();
    for (int j = 1; j <= db.StoredProcedures.Count; j++) {
      lstObjects.Items.Add(db.StoredProcedures.Item(j, "dbo").Name);
    }
    break;
  }
}

注意:SQLDMO 已停止更新,SQL Server 2012+ 不再包含,僅適用於 2000/2005/2008/R2 環境。

方案二:ODBC 底層 API(無需 COM,跨版本、輕量)

public class SqlLocator {
  // P/Invoke 簽名
  [DllImport("odbc32.dll")] private static extern short SQLAllocHandle(short hType, IntPtr inputHandle, out IntPtr outputHandle);
  [DllImport("odbc32.dll")] private static extern short SQLSetEnvAttr(IntPtr henv, int attribute, IntPtr valuePtr, int strLength);
  [DllImport("odbc32.dll")] private static extern short SQLFreeHandle(short hType, IntPtr handle);
  [DllImport("odbc32.dll", CharSet = CharSet.Ansi)] private static extern short SQLBrowseConnect(IntPtr hconn, StringBuilder inString, short inStringLength, StringBuilder outString, short outStringLength, out short outLengthNeeded);

  private const short SQL_HANDLE_ENV = 1, SQL_HANDLE_DBC = 2;
  private const int SQL_ATTR_ODBC_VERSION = 200, SQL_OV_ODBC3 = 3;
  private const short SQL_SUCCESS = 0, SQL_NEED_DATA = 99;
  private const short DEFAULT_RESULT_SIZE = 1024;
  private const string SQL_DRIVER_STR = "DRIVER=SQL Server";

  public static string[] GetServers() {
    string list = string.Empty;
    IntPtr henv = IntPtr.Zero, hconn = IntPtr.Zero;
    StringBuilder inStr = new StringBuilder(SQL_DRIVER_STR);
    StringBuilder outStr = new StringBuilder(DEFAULT_RESULT_SIZE);
    short inLen = (short)inStr.Length, lenNeeded = 0;

    try {
      if (SQLAllocHandle(SQL_HANDLE_ENV, henv, out henv) == SQL_SUCCESS &&
          SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (IntPtr)SQL_OV_ODBC3, 0) == SQL_SUCCESS &&
          SQLAllocHandle(SQL_HANDLE_DBC, henv, out hconn) == SQL_SUCCESS) {
        short ret = SQLBrowseConnect(hconn, inStr, inLen, outStr, DEFAULT_RESULT_SIZE, out lenNeeded);
        if (ret == SQL_NEED_DATA) {
          if (DEFAULT_RESULT_SIZE < lenNeeded) {
            outStr.Capacity = lenNeeded;
            if (SQLBrowseConnect(hconn, inStr, inLen, outStr, lenNeeded, out lenNeeded) != SQL_NEED_DATA)
              throw new ApplicationException("無法從 ODBC 驅動獲取 SQL Server 列表");
          }
          list = outStr.ToString();
          int start = list.IndexOf("{") + 1;
          int len = list.IndexOf("}") - start;
          if (start > 0 && len > 0) list = list.Substring(start, len);
          else list = string.Empty;
        }
      }
    } catch { list = string.Empty; }
    finally {
      if (hconn != IntPtr.Zero) SQLFreeHandle(SQL_HANDLE_DBC, hconn);
      if (henv != IntPtr.Zero) SQLFreeHandle(SQL_HANDLE_ENV, henv);
    }
    return list.Length > 0 ? list.Split(',') : null;
  }
}

方案對比與選型建議

維度SQLDMOODBC API
依賴SQLDMO COM 組件(需安裝客戶端工具)僅 odbc32.dll(系統自帶)
版本支持≤ SQL 2008 R2所有版本(含 2012/2014/2016/2017/2019/2022)
功能豐富度極高(對象模型完整)僅枚舉服務器名
部署複雜度需註冊 COM、位數匹配零部署,P/Invoke 即用
推薦場景舊系統維護、需操作對象屬性新開發、僅需發現服務器、跨版本兼容

現代替代:SMO (Microsoft.SqlServer.Management.Smo)

SQL Server 2005+ 官方托管 SDK,NuGet 安裝 Microsoft.SqlServer.SqlManagementObjects:

var server = new Server(".");
server.ConnectionContext.LoginSecure = true;
server.ConnectionContext.Connect();
foreach (Database db in server.Databases) Console.WriteLine(db.Name);

結論:新項目首選 SMO;舊項目維護用 SQLDMO;僅需枚舉實例名用 ODBC API 或 SqlDataSourceEnumerator.Instance.GetDataSources()(ADO.NET 內置)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved