13 junio 2010

SQLite desde C#

SQlite es un gestor de bases de datos, que permite hacer consultas usando el lenguaje SQL, y que se puede incluir como parte de un programa en C o C++, apenas incluyendo un fichero DLL adicional... o incluso ni eso, ya que realmente es una biblioteca que se puede "incrustar" como parte del programa.

Desde C# no puede usar la DLL de SQLite directamente, pero sí a través de otras como System.Data.Sqlite.Dll, que se puede encontrar en

http://sqlite.phxsoftware.com/

Con esa DLL, junto con la original de SQLite, podremos hacer programas en C# que nos permitan acceder a bases de datos y que sean fáciles de distribuir. SQLite se puede encontrar en

http://www.sqlite.org/

Vamos a ver un pequeño ejemplo de cómo crear una base de datos, cómo introducir datos y cómo mostrarlos. Primero veremos los fragmentos de código, luego un fuente completo, después cómo compilarlo y probarlo, y finalmente incluiré la descarga completa, con fuentes, ejecutable y DLLs.

Para conectar con la base de datos, crearíamos un objeto de tipo "SQLiteConnection":


conexion =
new SQLiteConnection
("Data Source=personal.sqlite;Version=3;New=True;Compress=True;");
conexion.Open();


Para consultas de creación y modificación, crearemos un objeto de tipo SQLiteCommand y lo ejecutaremos con "ExecuteNonQuery()":


string creacion = "CREATE TABLE ciudad "
+"(codigo VARCHAR(2) PRIMARY KEY, nombre VARCHAR(30));";
SQLiteCommand cmd = new SQLiteCommand(creacion, conexion);
cmd.ExecuteNonQuery();


Si se trata de una consulta que sí devuelve datos (un "select"), usaremos "ExecuteReader()" y leeremos datos de forma repetitiva con "while (datos.Read())"


string consulta = "select * from ciudad";
SQLiteCommand cmd = new SQLiteCommand(consulta, conexion);
SQLiteDataReader datos = cmd.ExecuteReader();
// Leemos los datos de forma repetitiva
while (datos.Read())
{
string codigo = Convert.ToString(datos[0]);
string nombre = Convert.ToString(datos[1]);
// Y los mostramos
Console.WriteLine("Codigo: {0}, Nombre: {1}",
codigo, nombre);
}


En los "ExecuteNonQuery", podemos comprobar la cantidad de datos afectados, lo que nos puede ayudar a descubrir errores:


cantidad = cmd.ExecuteNonQuery();
if (cantidad < 1)
Console.WriteLine("No se ha podido insertar");



Aun así, muchos tipos de errores, como una clave duplicada, pueden provocar que salte una excepción y se interrumpa el programa, por lo que sería recomendable incluir las órdenes de inserción dentro de un bloque "try...catch"


En cualquier caso, al terminar de acceder deberemos cerrar la conexión a la base de datos:


conexion.Close();





El fuente completo podría ser así:

// Ejemplo de acceso a SQLite desde C#
// Nacho Cabanes, junio 2010

using System;
using System.IO;
using System.Data.SQLite; //Utilizamos la DLL


public class pruebaSQLite01
{
static SQLiteConnection conexion;

private static void CrearBBDDSiNoExiste()

{
if (!File.Exists("personal.sqlite") )

{
// Creamos la conexion a la BD.
// El Data Source contiene la ruta del archivo de la BD
conexion =
new SQLiteConnection
("Data Source=personal.sqlite;Version=3;New=True;Compress=True;");

conexion.Open();

// Creamos la primera tabla
string creacion = "CREATE TABLE ciudad "
+"(codigo VARCHAR(2) PRIMARY KEY, nombre VARCHAR(30));";

SQLiteCommand cmd = new SQLiteCommand(creacion, conexion);
cmd.ExecuteNonQuery();

// Creamos la segunda tabla

creacion = "CREATE TABLE persona "
+"(codigo VARCHAR(2) PRIMARY KEY, nombre VARCHAR(30),"
+" codigoCiudad VARCHAR(2) );";
cmd = new SQLiteCommand(creacion, conexion);

cmd.ExecuteNonQuery();
}
else
{
// Creamos la conexion a la BD.

// El Data Source contiene la ruta del archivo de la BD
conexion =
new SQLiteConnection
("Data Source=personal.sqlite;Version=3;New=False;Compress=True;");
conexion.Open();

}
}


private static void InsertarDatos()

{

string insercion; // Orden de insercion, en SQL
SQLiteCommand cmd; // Comando de SQLite
int cantidad; // Resultado: cantidad de datos


try
{
insercion = "INSERT INTO ciudad "+
"VALUES ('t','Toledo');";
cmd = new SQLiteCommand(insercion, conexion);

cantidad = cmd.ExecuteNonQuery();
if (cantidad < 1)

Console.WriteLine("No se ha podido insertar");

insercion = "INSERT INTO ciudad "+
"VALUES ('a','Alicante');";

cmd = new SQLiteCommand(insercion, conexion);
cantidad = cmd.ExecuteNonQuery();

if (cantidad < 1)
Console.WriteLine("No se ha podido insertar");


insercion = "INSERT INTO persona "+
"VALUES ('j','Juan','t');";
cmd = new SQLiteCommand(insercion, conexion);

cantidad = cmd.ExecuteNonQuery();
if (cantidad < 1)

Console.WriteLine("No se ha podido insertar");

insercion = "INSERT INTO persona "+
"VALUES ('p','Pepe','t');";

cmd = new SQLiteCommand(insercion, conexion);
cantidad = cmd.ExecuteNonQuery();

if (cantidad < 1)
Console.WriteLine("No se ha podido insertar");

}
catch (Exception e)
{
Console.WriteLine("No se ha podido insertar");

Console.WriteLine("Posiblemente un código está repetido");
Console.WriteLine("Error encontrado: {0} ", e.Message);

}
}

private static void MostrarCiudades()

{
// Lanzamos la consulta y preparamos la estructura para leer datos
string consulta = "select * from ciudad";
SQLiteCommand cmd = new SQLiteCommand(consulta, conexion);

SQLiteDataReader datos = cmd.ExecuteReader();
// Leemos los datos de forma repetitiva
while (datos.Read())

{
string codigo = Convert.ToString(datos[0]);

string nombre = Convert.ToString(datos[1]);
// Y los mostramos

Console.WriteLine("Codigo: {0}, Nombre: {1}",
codigo, nombre);
}

}


private static void MostrarPersonas()
{

// Lanzamos la consulta y preparamos la estructura para leer datos
string consulta = "select * from persona";
SQLiteCommand cmd = new SQLiteCommand(consulta, conexion);

SQLiteDataReader datos = cmd.ExecuteReader();
// Leemos los datos de forma repetitiva
while (datos.Read())

{
string codigo = Convert.ToString(datos[0]);

string nombre = Convert.ToString(datos[1]);
// Y los mostramos

Console.WriteLine("Codigo: {0}, Nombre: {1}",
codigo, nombre);
}

}

private static void MostrarCiudadesYPersonas()
{

// Lanzamos la consulta y preparamos la estructura para leer datos
string consulta =
"select persona.nombre, ciudad.nombre "+
"from persona, ciudad "+
"where persona.codigoCiudad = ciudad.Codigo";

SQLiteCommand cmd = new SQLiteCommand(consulta, conexion);
SQLiteDataReader datos = cmd.ExecuteReader();

// Leemos los datos de forma repetitiva
while (datos.Read())
{
string nombrePersona = Convert.ToString(datos[0]);

string nombreCiudad = Convert.ToString(datos[1]);
// Y los mostramos

Console.WriteLine("{0} vive en {1}",
nombrePersona, nombreCiudad);
}

}

private static void CerrarBBDD()
{

conexion.Close();
}


public static void Main()

{
Console.WriteLine("Accediendo...");
CrearBBDDSiNoExiste();

Console.WriteLine("Añadiendo datos...");
InsertarDatos();
Console.WriteLine("Datos de ciudades:");

MostrarCiudades();
Console.WriteLine("Datos de personas:");
MostrarPersonas();

Console.WriteLine("Datos de personas y ciudades:");
MostrarCiudadesYPersonas();
CerrarBBDD();

}

}






Para compilar este fuente, deberemos incluir "System.Data.SqLite.dll" dentro de las referencias del proyecto. Esto se haría desde el propio entorno visual si usamos herramientas como Visual Studio o SharpDevelop, o bien añadiendo la opción /r si compilamos desde línea de comandos, por ejemplo usando Mono:

gmcs pruebaSQLite.cs /r:System.Data.SqLite.dll







Y aquí puedes descargar el fuente, los ficheros DLL y el ejecutable: csharp_sqlite.zip



8 comentarios:

Unknown dijo...

Me encanto!!! muchisimas gracias!!

Luix_Solier dijo...

Oe men no tendras por ahi una codigo completo de como usar una tabla hash o tabla de dispersion te lo agredecere un monton!!! pliss

Nacho Cabanes dijo...

Para dudas sobre C#, especialmente si no son relacionadas con este artículo concreto, me encontrarás en el foro de AprendeAProgramar:

http://www.aprendeaprogramar.com/mod/forum/view.php?id=372

Anónimo dijo...

Esta bien el aporte pero tengo una duda!, el aporte esta en modo conectado con la BD, y yo lo quiero hacer en modo desconectado, el caso es.. que en un formulario relleno un datagrid con dataAdpter.fill(dataset);
en el constructor de este formulario, pero luego quiero realizar una busqueda por lo que le pases en un campo de texto y que el datagrid se actualice es decir hacer un select.. por lo tanto cuando pongo:
dataAdapter.SelectComand.ComandText = select...
dataAdapter.fill(dataset);
da error porque el dataset ya estab relleno anteriormente en el constructor

Unknown dijo...

Si uso SQLite en mi programa, ¿es necesario que en el ordenador del cliente se encuentre instalada alguna DLL o programa adicional?

Gracias ^^

Unknown dijo...
Este comentario ha sido eliminado por el autor.
Nacho Cabanes dijo...

Efectivamente. Las dos DLL que menciono (la propia de SQLite y "System.Data.Sqlite.Dll") tendrán que estar en la misma carpeta que el ejecutable de tu programa, o bien en alguna ruta del sistema (como la carpeta System32 de Windows).

Jose dijo...

Todo me parece muy bueno, mi duda es si se puede poner claves foraneas en sqlite, es posible?