Bases de datos locales en Windows Phone

Hola a todos!

Después de investigar y hacer mis pruebas, voy a explicar en forma sencilla cómo utilizar una base de datos local para manejar datos en Windows Phone 7.x. Esta ocasión vamos a trabajar con SQL Server CE (Compact Edition), que es la opción que nos da Microsoft.

Como ya sabemos, Windows Phone utiliza almacenamiento aislado, lo que significa que nuestra aplicación solamente puede acceder al espacio que le corresponde, no pudiendo compartir una misma base de datos con varias aplicaciones. SQL Server CE utiliza archivos sdf para almacenar nuestra base de datos, y utilizaremos la ruta "isostore:/" para acceder al almacenamiento aislado en donde se guardará nuestra base de datos.

Introduciéndonos en la programación, vamos a utilizar LINQ to SQL para acceder a nuestros datos, y vamos a implementar el modelo "code first" (código primero) para crear y mapear nuestras tablas.

Bien, para empezar a trabajar con SQL Server CE debemos agregar la referencia al ensamblado System.Data.Linq en nuestra aplicación. Añadiremos un using a este namespace y otro a System.Data.Linq.Mapping.

Ahora vamos a crear nuestra primera clase Clientes la cual contiene los atributos necesarios y los mapeos a su tabla correspondiente:

using System.Data.Linq.Mapping;

namespace Tornado.PanoramaWindowsPhone
{
    [Table(Name="Clientes")]
    public class Cliente
    {
        [Column(IsPrimaryKey = true, IsDbGenerated = true)]
        public int Id { get; set; }

        [Column(CanBeNull = false)]
        public string Codigo { get; set; }

        [Column(CanBeNull = false)]
        public string Denominacion { get; set; }

        [Column(CanBeNull = true)]
        public string Domicilio { get; set; }

        [Column(CanBeNull = true)]
        public string Telefono { get; set; }

        [Column(CanBeNull = true)]
        public string Email { get; set; }

        [Column(CanBeNull = false)]
        public float PorcentajeDescuento { get; set; }
    }
}

Bien, como verán es una clase común y corriente a la cual le agregamos atributos de System.Data.Linq.Mapping. El atributo Table sobre la clase, la identifica como una tabla, en donde el parámetro Name especifica el nombre de la tabla relacionada en la base de datos. El atributo Column establece características a cada propiedad, como si es una clave primaria, si la misma es autogenerada por la base de datos, si permite o no valores nulos, entre otros.

Ya creada nuestra clase Clientes, pasamos a crear nuestra clase contexto de datos. Esta clase va a heredar de la clase DataContext del ensamblado System.Data.Linq, el cual nos va a dar toda la funcionalidad necesaria para poder trabajar con nuestra base de datos.

using System.Data.Linq;

namespace Tornado.PanoramaWindowsPhone
{
    public class TornadoDbContext : DataContext
    {
        public TornadoDbContext(string connectionString)
            : base(connectionString)
        {
        }

        public Table<Cliente> Clientes
        {
            get
            {
                return this.GetTable<Cliente>();
            }
        }
    }
}

La clase tiene una propiedad Clientes tipo Table para exponer nuestra tabla Clientes. El constructor requiere un parámetro que contenga la ruta (o cadena de conexión) a nuestro archivo de base de datos. Recuerden que al tener almacenamiento aislado, la cadena de conexión a la base de datos será Data Source='isostore:/Datos.sdf'.

Para comenzar a utilizar nuestra base de datos, añadimos el siguiente código en el código de MainPage.xaml:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using Microsoft.Phone.Controls;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Collections.ObjectModel;
using System.Text;
using Microsoft.Phone.Net.NetworkInformation;

namespace Tornado.PanoramaWindowsPhone
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        public MainPage()
        {
            InitializeComponent();

            using (TornadoDbContext context = new TornadoDbContext("Data Source='isostore:/Datos.sdf'"))
            {
                if (!context.DatabaseExists())
                {
                    context.CreateDatabase();
                }
            }
        }
    }
}

Lo que hacemos es crear nuestra clase contexto, consultamos si existe la base de datos y, en caso que no exista la creamos.

Siguiendo con el ejemplo anterior, luego de verificar y crear la base de datos en caso que no exista, muestro un ejemplo de cómo agregar registros a nuestra tabla clientes:


using (TornadoDbContext context = new TornadoDbContext("Data Source='isostore:/Datos.sdf'"))
{
    if (!context.DatabaseExists())
    {
        context.CreateDatabase();
    }
 
    Cliente newCliente = new Cliente()
    {
        Codigo = "01",
        Denominacion = "Cliente 01",
        Domicilio = "Calle Muro 1256",
        Email = "cliente@mail.com",
        Telefono = "",
        PorcentajeDescuento = 0
    };
    context.Clientes.InsertOnSubmit(newCliente);
    context.SubmitChanges();
}


Otra forma de agregar registros, pero esta vez en forma masiva, es la siguiente:

using (TornadoDbContext context = new TornadoDbContext("Data Source='isostore:/Datos.sdf'"))
{
    if (!context.DatabaseExists())
    {
        context.CreateDatabase();
    }

    List<Cliente> newClientesList = new List<Cliente>()
    {
        new Cliente()
        {
            Codigo = "01",
            Denominacion = "Cliente 01",
            Domicilio = "Calle Muro 1256",
            Email = "cliente@mail.com",
            Telefono = "",
            PorcentajeDescuento = 0
        },
        new Cliente()
        {
            Codigo = "02",
            Denominacion = "Cliente 02",
            Domicilio = "Calle Muro 653",
            Email = "cliente02@mail.com",
            Telefono = "",
            PorcentajeDescuento = 10
        }
    };
    context.Clientes.InsertAllOnSubmit(newClientesList);
    context.SubmitChanges();
}

Como se muestra en los ejemplos anteriores, utilizamos el método InsertOnSubmit para agregar un registro o InsertAllOnSubimit para agregar varios registros a la propiedad Clientes. Estos se crean con un estado pendiente de inserción.
Luego, para enviar los cambios a la base de datos, utilizamos el método SubmitChanges.

Por ultimo, para recuperar registros desde nuestra base de datos, utilizamos la propiedad Clientes de nuestro contexto como se muestra a continuación:

using (TornadoDbContext context = new TornadoDbContext("Data Source='isostore:/Datos.sdf'"))
{
    List<Cliente> clientesList = context.Clientes.ToList();
}

Como se ve, trabajar con datos locales en Windows Phone 7.x es muy sencillo.
Espero que les sea de utilidad.

Saludos a todos!

Comentarios

RobertoP ha dicho que…
Muy bueno Cumpa!

Entradas populares de este blog

Integration Services y Visual FoxPro Databases

Agregar proyecto existente al Project Explorer de Eclipse