martes, 22 de enero de 2013

Bases de datos locales en Windows Store Apps

Una de las dificultades a las que nos hemos enfrentado al momento de desarrollar un aplicación del tipo Windows Store App, es la imposibilidad de contar con una base de datos relacional "nativa" en este entorno.

Un tiempo atrás se podía llegar a lograr esto, utilizando SQLite, aunque podía llegar a ser un proceso bastante "complicado" por llamarlo de alguna manera.

Afortunadamente, el equipo de SQLite se ha encargado de facilitarnos bastante la vida reduciendo significativamente la complejidad necesaria para utilizar dicha base en nuestros proyectos.

El objetivo de este post, es tratar de explicarle, los pasos necesarios para incluir una base SQLite en su proyecto.

Primer paso:

Lo primero que debe hacer es, obtener el paquete de SQLite propiamente dicho. Para ello tiene que seleccionar del menú principal la opción Tools|Extensions and Updates  (esto depende claro está, del idioma en el que tenga Visual Studio) . En la ventana de extensiones y actualizaciones, seleccione "Online" y luego escriba "sqlite" en el cuadro de búsqueda. Si todo va bien, debería ver la opción "SQLite for Windows Runtime", presione el botón instalar. Por último, debe agregar las referencias del paquete recién instalado y del Runtime de VC++ y ya tendría listo el primer paso. Para ello, debe ir al menú contextual dentro del proyecto y seleccionar "Add References". A continuación dejo unas capturas de como debería verse la secuencia de este primer paso:


 
 
 
 

Antes de pasar al segundo paso, cabe aclarar que si quisiéramos compilar el proyecto en este momento, probablemente nos daría un error. Esto sucede porque por defecto, cuando creamos un Windows Store Project, la compilación esta marcada como "Any CPU". Como hemos agregado este paquete de SQLite, esto no va a ser posible, por lo que deberemos compilar un paquete por cada plataforma para la cual deseemos generar. Esto se realiza seleccionando del menú principal la opción Build|Configuration Manager y seleccionando la plataforma deseada x86, x64 o ARM. Esto se aplica también si utilizamos otras dlls, por ejemplo, bing maps. Es un proceso engorroso, pero lo bueno de todo esto, es que cuando un usuario se descargue la aplicación, el store seleccionará automáticamente el paquete que aplique a su plataforma.



 


Segundo paso:

Antes de empezar a trabajar con la base, vamos a necesitar un paquete llamado sqlite-net. sqlite-net es una librería open source, que nos va a permitir trabajar con la base de datos SQLite de una manera mas amigable utilizando sintaxis del tipo LINQ. La manera mas sencilla que hay de agregar esta librería a nuestro proyecto, es presionar el botón derecho sobre la solución y seleccionar la opción "Manage NuGet Packages for Solution". En la ventana de Manage Nuget Packages, seleccione la opción Online y escriba sqlite-net en el cuadro de búsqueda. Después que instale dicho paquete, verá que se han agregado dos nuevos archivos a la solución: SQLite.cs  y SQLiteAsync.cs.



 
 
Manos a la obra!
 
Ahora que tenemos todo listo, debemos abrir el archivo App.xaml y agregar el  código de inicialización de la base:
 
// Obtiene una referencia a la base de datos
DbPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "CMT.db");
// Inicializa la base si es necesario
using (var db = new SQLite.SQLiteConnection(DbPath))
{
// Crear las tablas si las mismas no existen
db.CreateTable<Customer>();
db.CreateTable<Project>();
}

 

 

Tanto la entidad Customer, como la entidad Project, son clases POCO básicas que no tienen mayor complejidad.
El único detalle que vale mencionar, es el atributo de Primary Key de SQLite. Actualización: Les recomiendo ver la página de características de sqlite-net para ver todos los decorados que podemos utilizar en la clase.
 
 
public class Customer
{
    [SQLite.PrimaryKey]
    public int Id { get; set; }
    public string Name { get; set; }
    public string City { get; set; }
    public string Contact { get; set; }
}
 
 
public class Project
{
    [SQLite.PrimaryKey]
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public DateTime DueDate { get; set; }
}

  
A continuación y a modo de ejemplo, se muestra el método GetCustomer, que retorna un cliente dado su Id.

public CustomerViewModel GetCustomer(int customerId)
{    
   var customer = new CustomerViewModel();    
   using (var db = new SQLite.SQLiteConnection(app.DBPath))    
   {        
     var _customer = (db.Table<Customer>().Where( c => c.Id == customerId)).Single();                
         customer.Id = _customer.Id;        
         customer.Name = _customer.Name;        
         customer.City = _customer.City;        
         customer.Contact = _customer.Contact;    
   }    
   return customer;
}


Si quieren el código de una aplicación completamente funcional, pueden bajar un ejemplo de aquí
 

Si quieren ejemplos de código de sqlite-net, pueden bajar un proyecto entero de aquí


Referencias:

http://timheuer.com/blog/archive/2012/05/20/using-sqlite-in-metro-style-app.aspx

http://timheuer.com/blog/archive/2012/08/07/updated-how-to-using-sqlite-from-windows-store-apps.aspx

http://blogs.msdn.com/b/robertgreen/archive/2012/11/13/using-sqlite-in-windows-store-apps.aspx

http://www.sqlite.org/

https://github.com/praeclarum/sqlite-net


Espero que les haya gustado y les sea de utilidad,
 
Hasta la próxima!