You are on page 1of 8

Introduccin

Lo que vamos a ver en este truco, ya que por extensin no llega a ganarse el "tipo" de artculo, es cmo crear mediante cdigo de Visual C# (cualquier versin 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 tambin ser el predeterminado, es ms la conexin la haremos usando autenticacin de Windows, por tanto, este cdigo 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 autenticacin de Windows, pero no ser lo habitual. Adems de que tampoco es la intencin 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 aplicacin la vas a usar en otro equipo en el que el usuario no tenga esos permisos, tendrs que cambiar la cadena de conexin, en la que tendrs que indicar el usuario y password que tenga privilegios suficientes. Para usar el siguiente cdigo, debes tener en las referencias el espacio de nombres System.Data y usaremos bsicamente una conexin (SqlConnection) y un comando (SqlCommand). El cdigo es para Visual C#, si quieres hacer esto mismo en Visual Basic, pulsa en el link anterior. Por qu separo el cdigo de VB del de C#? Para ver si vale la pena poner el cdigo en los dos lenguajes o sera mejor no "comerme el coco" y dejar solo el de Visual Basic, ya que mucha gente cree que en el sitio del Guille solo hay cdigo de VB y as, pues, se si tengo que "alargar" los artculos (o trucos) o no. Bueno, vamos a lo que vamos! Para probar este cdigo, crea un nuevo proyecto de Windows, aade tres etiquetas, a una de ellas le das el nombre de LableInfo y le asignas la propiedad Dock para que se site en la parte inferior del formulario, un comboBox (cboInstancias), una caja de textos (txtBase) y un botn (btnCrearBase). El aspecto del formulario es como el de la siguiente figura:

Figura 1. El formulario en tiempo de diseo

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 dars cuenta de que el formulario (en modo de diseo) 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 cdigo 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 tambin deducirs que en este cdigo te voy a mostrar cmo saber las instancias que hay instaladas en el equipo. Pues s, tienes razn, y el cdigo usado es uno que lo averigua mirando en el registro de Windows. Ahora vers cmo se hace, de hecho, he puesto el cdigo en una funcin separada para que la puedas "copiar y pegar" fcilmente y no hace falta hacer ninguna exportacin de espacios de nombres, ya que he declarado las variables, etc. usando el nombre completo. As que, empecemos viendo esa funcin 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\Mic rosoft\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 separndolos 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 tambin por eso, hacemos un cast para convertir el valor devuelto por GetValue (que es de tipo object) en el array que devolver la funcin. La instancia predeterminada de SQL Server tiene el nombre de MSSQLSERVER, pero en esta funcin no hacemos nada con ese "nombre", ya que ser en el cdigo 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 versin de VS De ese "pequeo" detalle de "componer" correctamente el nombre de la instancia, (sin el que no podramos crear la base de datos), se encarga el cdigo 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 cdigo que se encarga de crear la base de datos.

Crear una base de datos de SQL Server desde cdigo 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 cdigo del botn 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 deberas 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 cdigo del botn "Crear base". En este caso, debes tener una importacin 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 conexin 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 conexin 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 conexin est abierta if(cnn.State == ConnectionState.Open) { cnn.Close(); } } LabelInfo.Refresh(); }

Este es el cdigo de Visual C# para abrir la "base de datos" (ms abajo tienes el cdigo completo de C# del formulario):
string sBase = txtFic.Text; string sSelect = "SELECT * FROM " + txtSelect.Text; string sConn;

sConn = "Driver={Microsoft Visual FoxPro Driver};SourceType=DBF;SourceDB=" + System.IO.Path.GetDirectoryName(sBase) + ";";

using (System.Data.Odbc.OdbcConnection dbConn = new System.Data.Odbc.OdbcConnection(sConn)) { try { dbConn.Open();

System.Data.Odbc.OdbcDataAdapter da = new System.Data.Odbc.OdbcDataAdapter(sSelect, dbConn); DataTable dt = new DataTable();

da.Fill(dt);

dgvDiarios.DataSource = dt;

dbConn.Close();

} catch (Exception ex) { MessageBox.Show("Error al abrir la base de datos\n" + ex.Message); return; } } public partial class Form1 : Form { public Form1() { InitializeComponent(); }

private void Form1_DragEnter(object sender, DragEventArgs e) { // Drag & Drop, comprobar con DataFormats if (e.Data.GetDataPresent(DataFormats.FileDrop)) { e.Effect = DragDropEffects.Copy; } }

private void Form1_DragDrop(object sender, DragEventArgs e) { // Drag & Drop, aceptar el primer fichero if (e.Data.GetDataPresent("FileDrop")) { txtFic.Text = ((String[])e.Data.GetData("FileDrop", true))[0]; txtSelect.Text = System.IO.Path.GetFileNameWithoutExtension(txtFic.Text); } }

private void btnExaminar_Click(object sender, EventArgs e) { OpenFileDialog oFD = new OpenFileDialog();

oFD.Filter = "Ficheros DBF (*.dbf)|*.dbf|Todos (*.*)|*.*"; oFD.FileName = txtFic.Text; if (oFD.ShowDialog() == DialogResult.OK) { txtFic.Text = oFD.FileName; // El nombre del fichero txtSelect.Text = System.IO.Path.GetFileNameWithoutExtension(txtFic.Text); btnAbrir_Click(null, null); } }

private void btnAbrir_Click(object sender, EventArgs e) { string sBase = txtFic.Text; string sSelect = "SELECT * FROM " + txtSelect.Text; string sConn;

sConn = "Driver={Microsoft Visual FoxPro Driver};SourceType=DBF;SourceDB=" + System.IO.Path.GetDirectoryName(sBase) + ";";

using (System.Data.Odbc.OdbcConnection dbConn = new System.Data.Odbc.OdbcConnection(sConn)) { try { dbConn.Open();

System.Data.Odbc.OdbcDataAdapter da = new System.Data.Odbc.OdbcDataAdapter(sSelect, dbConn); DataTable dt = new DataTable();

da.Fill(dt);

dgvDiarios.DataSource = dt;

dbConn.Close();

} catch (Exception ex) { MessageBox.Show("Error al abrir la base de datos\n" + ex.Message);

return; } } } }

System.Data System.Data.Odbc System.IO