lunes, 15 de febrero de 2010

Crear una base de datos de SQL Server mediante código de Visual C#

Introducción

Lo que vamos a ver en este truco, ya que por extensión no llega a ganarse el "tipo" de artículo, es cómo crear mediante código de Visual C# (cualquier versión para .NET) una base de datos de SQL Server.
Esa base de datos se almacenará en la carpeta predeterminada de SQL Server y el usuario también será el predeterminado, es más la conexión la haremos usando autenticación de Windows, por tanto, este código solo te servirá si esa base de datos la creas localmente, es decir, no servirá para crear la base en un servidor remoto, salvo que tengas acceso a ese servidor usando la autenticación de Windows, pero no será lo habitual. Además de que tampoco es la intención de este "truco", ya que en realidad la utilidad será para usarlo desde aplicaciones "normales" de Windows o aplicaciones de escritorio.
Por supuesto, el usuario de Windows debe tener "permisos" para hacer esto, por tanto, si la aplicación la vas a usar en otro equipo en el que el usuario no tenga esos permisos, tendrás que cambiar la cadena de conexión, en la que tendrás que indicar el usuario y password que tenga privilegios suficientes.
Para usar el siguiente código, debes tener en las referencias el espacio de nombres System.Data y usaremos básicamente una conexión (SqlConnection) y un comando (SqlCommand).


Para probar este código, crea un nuevo proyecto de Windows, añade tres etiquetas, a una de ellas le das el nombre de LableInfo y le asignas la propiedad Dock para que se sitúe en la parte inferior del formulario, un comboBox (cboInstancias), una caja de textos (txtBase) y un botón (btnCrearBase). El aspecto del formulario es como el de la siguiente figura:
Figura 1. El formulario en tiempo de diseño
Figura 1. El formulario en tiempo de diseño
Como puedes observar, o imaginarte al ver la figura 1, en el combo mostraremos las instancias de SQL Server que hay instaladas en el equipo, y por defecto estará seleccionada la principal (local), pero puedes crear la base de datos en la instancia que quieras.
Seguramente te darás cuenta de que el formulario (en modo de diseño) no es un formulario de Visual Studio 2003, sino de Visual C# 2005, pero no te preocupes... ¡quieto parao! ¡no te vayas! ya que el código vale para todas las versiones de Visual C# (2002, 2003, 2005 y hasta para la 2007 cuando salga).

Saber las instancias de SQL Server que hay instaladas (C#)

Suponiendo que discurres un poco, je, je, cosa que no dudo, seguramente también deducirás que en este código te voy a mostrar cómo saber las instancias que hay instaladas en el equipo. Pues sí, tienes razón, y el código usado es uno que lo averigua mirando en el registro de Windows. Ahora verás cómo se hace, de hecho, he puesto el código en una función separada para que la puedas "copiar y pegar" fácilmente y no hace falta hacer ninguna exportación de espacios de nombres, ya que he declarado las variables, etc. usando el nombre completo.
Así que, empecemos viendo esa función que nos dice las instancias de SQL Server que hay instaladas  en nuestro equipo.
private string[] instanciasInstaladas()
{
    Microsoft.Win32.RegistryKey rk;
    rk = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Microsoft SQL Server", false);
    string[] s;
    s = ((string[])rk.GetValue("InstalledInstances"));
    return s;
}
La clave InstalledInstances es una clave del tipo REG_MULTI_SZ, que internamente guarda los valores separándolos con caracteres '\0', pero que al leer el valor convertirlo usando un "cast" a array de tipo string, pues tenemos cada uno de los valores de forma separada, por eso, devolvemos un array de tipo string, y también por eso, hacemos un cast para convertir el valor devuelto por GetValue (que es de tipo object) en el array que devolverá la función.
La instancia predeterminada de SQL Server tiene el nombre de MSSQLSERVER, pero en esta función no hacemos nada con ese "nombre", ya que será en el código que se encarga de asignarlo en el combo el que lo cambiará por (local), que es la forma habitual de usar la instancia predeterminada.
El resto de nombres de instancias, son precisamente eso los nombres de instancias, pero si las usamos así "a pelo", pues no nos funcionará, ya que esas instancias siempre tendremos que usarlas "dentro" de la principal, por ejemplo, cuando instalamos el Visual Studio 2005 o el Visual C# 2005 Express, se crea una instancia llamada SQLEXPRESS, pero para usar esa instancia, tendremos que hacerlo de dos formas, una usando (local) delante de esa instancia: (local)\SQLEXPRESS y la otra es usando el nombre del equipo, por ejemplo: ELGUILLE\SQLEXPRESS.
En Visual Studio .NET y el MSDE se crea una instancia llamada NETSDK, por tanto si tienes instalado el VS2005 y el VS2003, te mostrará esto:
Figura 2. Las instancias instaladas suelen depender de la versión de VS
Figura 2. Las instancias instaladas suelen depender de la versión de VS

De ese "pequeño" detalle de "componer" correctamente el nombre de la instancia, (sin el que no podríamos crear la base de datos), se encarga el código que "rellena" el combo con las instancias, que es el siguiente:
private void Form1_Load(object sender, EventArgs e)
{
    LabelInfo.Text = "Cargando las instancias...";
    this.Show();
 
    string[] instancias;
    instancias = instanciasInstaladas();
    foreach(string s in instancias)
    {
        if(s == "MSSQLSERVER")
        {
            cboInstancias.Items.Add("(local)");
        }
        else
        {
            cboInstancias.Items.Add(@"(local)\" + s);
        }
    }
    cboInstancias.Text = "(local)";
 
    LabelInfo.Text = "Indica la base de datos a crear y selecciona la instancia";
}
Como puedes comprobar, cuando la cadena es MSSQLSERVER la cambiamos por (local) y en el resto de los casos, ponemos (local)\ delante del nombre de la instancia.

Ahora veamos "por fin" el código que se encarga de crear la base de datos.

Crear una base de datos de SQL Server desde código de C#

Como  puedes apreciar en la figura 1, tenemos una caja de textos llamada txtBase que es en la que indicaremos el nombre de la base de datos. Por tanto, en el código del botón de crear la base usaremos tanto ese nombre de la base de datos que queremos usar como el nombre que haya en el combo, en el que puedes escribir lo que quieras, pero... solo deberías usar un nombre diferente a los mostrados si sabes con seguridad lo que vas a hacer... de todas formas, si se produce un error, pues no pasa mucho (espero), ya que se intercepta en un try/catch.
Veamos el código del botón "Crear base". En este caso, debes tener una importación a System.Data.SqlClient con idea de que podamos declarar los objetos que vamos a usar sin necesidad de anteponer ese espacio de nombres al nombre de cada una de las dos clases que vamos a usar.
private void btnCrearBase_Click(object sender, EventArgs e) {
LabelInfo.Text = "Creando la base de datos...";
LabelInfo.Refresh(); // La conexión a usar, indicando la base master
SqlConnection cnn = new SqlConnection( "Server=" + cboInstancias.Text + "; " + "database=master; integrated security=yes"); // La orden T-SQL para crear la tabla
string s = "CREATE DATABASE " + txtBase.Text; SqlCommand cmd = new SqlCommand(s, cnn);
try { // Abrimos la conexión y ejecutamos el comando
cnn.Open();
cmd.ExecuteNonQuery();
// LabelInfo.Text = "Base de datos creada correctamente"; }
catch(Exception ex) {
LabelInfo.Text = "Error al crear la base de datos";
MessageBox.Show(ex.Message, "Error al crear la base", MessageBoxButtons.OK, MessageBoxIcon.Error); }
finally { // Por si se produce un error, // comprobar si la conexión está abierta
if(cnn.State == ConnectionState.Open) { cnn.Close(); } }
LabelInfo.Refresh(); }
Como puedes ver, el comando que ejecutamos es: CREATE DATABASE seguida del nombre de la base de datos a crear, y la conexión la hacemos en la base de datos "master" ya que es la que contiene las bases de esa instancia.
Como "tip" extra, decirte que puedes usar el mismo nombre de base de datos en cada instancia de SQL Server, ya que cada instancia tiene su propio directorio para los datos.

Y esto es todo.
Espero que te sea de utilidad, que de eso es de lo que se trata.

No hay comentarios:

Publicar un comentario