2016/05/12

Obtener instancias de SQL Server y bases de datos disponibles desde C#

Por si alguna vez se te ha planteado la necesidad de mostrar un formulario con los orígenes de datos de SQL Server disponibles (algo como el formulario Agregar conexión de Visual Studio) voy a plantear un pequeño ejemplo.
Creamos un nuevo proyecto de Windows Forms al que llamaremos EDGAR_Group, y en él un formulario Form1 en el que añadimos 2 combobox: cmbServidores y cmbBasedeDatos.
En el código del formulario añadimos lo siguiente: 
using System;
using System.Data;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Data.Sql;
using System.Data.SqlClient;

namespace EDGAR_Group
{
    public partial class Form1 : Form
    {
        SqlDataSourceEnumerator servidores;
        DataTable tablaservidores;
        string servidor;

        public Form1()
        {
            InitializeComponent();
            servidores = SqlDataSourceEnumerator.Instance;
            tablaservidores = new DataTable();
        }        
    }
}
Ahora hay que añadir el código para el evento click de cada uno de los combobox:
Para obtener la lista de instancias de SQL Server disponibles usaremos el objeto SqlDataSourceEnumerator.Instance, concretamente el método GetDataSources() que nos devuelve un DataTable con las características de las instancias: nombre del servidor, nombre de instancia, si forma parte de un clúster y la versión (8.00.x para SQL Server 2000 y superiores):
private void cmbServidores_Click(object sender, EventArgs e)
{
    //Comprobamos que no se haya cargado ya el combobox
    if (tablaservidores.Rows.Count == 0)
    {
        // Obtenemos un dataTable con la información sobre las instancias visibles
        // de SQL Server 2000 y 2005
        tablaservidores = servidores.GetDataSources();


        // Creamos una lista para que sea el origen de datos del combobox
        List listaservidores = new List();
        
        // Recorremos el dataTable y añadimos un valor nuevo a la lista con cada fila
        foreach (DataRow rowServidor in tablaservidores.Rows)
        {
            // La instancia de SQL Server puede tener nombre de instancia 
            //o únicamente el nombre del servidor, comprobamos si hay 
            //nombre de instancia para mostrarlo
            if (String.IsNullOrEmpty(rowServidor["InstanceName"].ToString()))
                listaservidores.Add(rowServidor["ServerName"].ToString());
            else
                listaservidores.Add(rowServidor["ServerName"] + "\\" + rowServidor["InstanceName"]);
        }

        // Asignamos al origen de datos del combobox la lista con 
        // las instancias de servidores
        cmbServidores.DataSource = listaservidores;
    }
}

Y para que nos muestre las bases de datos tenemos que ejecutar una consulta sobre la vista sys.databases:
private void cmbBasedeDatos_Click(object sender, EventArgs e)
{
    string select;
    string cadenaConexion;
    List listaBasesdatos = new List();

    servidor = this.cmbServidores.Text;

    // Componemos la cadena de conexión con el servidor seleccionado 
    // con seguridad integrada
    // Si se conecta con usuario de SQL Server hay que cambiar 
    // la cadena de conexión
    cadenaConexion = "Data Source=" + servidor + ";Integrated Security=True;Initial Catalog=master";

    using (SqlConnection con = new SqlConnection(cadenaConexion))
    {
        // Abrimos la conexión
        con.Open();

        // Obtenemos los nombres de las bases de datos que haya en el servidor
        // se pueden filtrar para no mostrar las bases de datos de sistema
        select = "select name from sys.databases;";

        // Obtenemos un dataReader con el resultado
        SqlCommand com = new SqlCommand(select, con);
        SqlDataReader dr = com.ExecuteReader();

        // Recorremos el dataReader y añadimos un elemento nuevo 
        // por cada registro
        while (dr.Read())
        {
            listaBasesdatos.Add(dr[0].ToString());
        }

        // Asignamos la lista de bases de datos como origen de datos del combobox
        cmbBasedeDatos.DataSource = listaBasesdatos;
    }
}

Y ya está, con esto tenemos un formulario que permite seleccionar la instancia de SQL Server y la base de datos al que nos queremos conectar.
Si en vez de seguridad integrada usamos un usuario y password de SQL Server sólo hay que cambiar la cadena de conexión.

Puedes descargar el proyecto aqui