Reto Windows Azure: Almacenamiento en tablas no relacionales

Trabajar con SQL Azure es fácil e intuitivo porque es casi equivalente a SQL Server, pero SQL Azure no es el único sistema de almacenamiento disponible en la Plataforma Windows Azure. En este artículo vamos a hacer una pequeña introducción a otra posibilidad,  el servicio de tablas de Windows Azure Storage.

¡Herramientas!

Para seguir el laboratorio y hacer el reto que os proponemos, necesitaras algunas herramientas, nada muy complicado, pero sin ellas va a ser difícil que lo sigas! :)

Visual Studio. Si ya tienes VS instalado perfecto, pero por si acaso, aquí tienes el enlace de descarga de la versión gratuita express o de la Ultimate Trial

SDK de Windows Azure. Contiene las herramientas para Visual Studio y las librerías necesarias para trabajar en proyectos de Windows Azure.

SQL Express . Normalmente ya lo tendréis instalado por Visual Studio, pero por si las moscas

Si surge cualquier duda o complicación, no dudes en añadir un comentario a este post o comentárnoslo por twitter a @esmsdn o en el hashtag #retosmsdn

 

¿Windows Azure Storage?

Windows Azure Storage juega diferentes papeles dentro de la Plataforma Windows Azure. El servicio de almacenamiento en tablas no es el único que se ofrece bajo el paraguas de storage, vamos a hacer un breve repaso.

Tablas Aunque se llamen tablas, realmente no están implementadas como las tablas relacionales que nos puedan venir inmediatamente a la cabeza. Estas tablas se comportan de forma parecida a una colección de entidades. No hay esquema definido, relaciones, índices o lenguaje SQL para acceder.

Blobs Almacenamiento de objetos binarios de gran tamaño. Podemos almacenar imágenes, videos, discos duros virtuales… en definitiva cualquier recurso que requiera de gran espacio de almacenamiento.

Windows Azure Drive Aprovechando el servicio de Blobs comentado en el punto anterior, Windows Azure Drive ofrece un volumen VHD NTFS

Colas Más que un mecanismo de almacenamiento, son un mecanismo de comunicación asíncrona. La cola actúa como un almacén de mensajes donde las aplicaciones (cloud o no) pueden dejar mensajes o recogerlos. Podemos pensar en un modo de funcionamiento equivalente a MSMQ, System.Messaging o JMS. Aunque con sus propias características.

La información almacenada en los servicios de Windows Azure Storage está preparada para ser tolerante a fallos, Windows Azure realiza tres copias en diferentes dominios de fallo, para que nunca falten los datos. También se ofrece un servicio de red de distribución de contenidos (CDN).

Se puede acceder a estos servicios  a través de una interfaz REST aunque Microsoft ha construido SDKs para las principales plataformas.

El servicio de Storage Tables

El simulador local

Los servicios del storage se simulan sobre una instalación de SQL Server. El SDK monta una capa de abstracción y expone un endpoint por cada uno de los principales servicios (Tables, Queues y Blobs). La aplicación se construye atacando a este simulador local, y una vez esta construida se cambian las URLs y claves para apuntar al servicio en la nube.

Si se ha instalado el SDK ANTES de estar SQL Server instalado, habrá que ejecutar una herramienta (C:\Program Files\Windows Azure SDK\v1.4\bin\devstore\DSInit.exe) para que monte la capa de abstracción y exponga los endpoints.

Crear la cuenta en Windows Azure

No hace falta tener una suscripción activa para el ejercicio ni para el reto, es por si alguien quiere hacerlo directamente en la nube en lugar de en el simulador local.

Todos los servicios del storage dependen de una única cuenta de storage que debemos de activar en nuestra suscripción de Windows Azure. El proceso es muy sencillo, una vez nos registramos en el portal de administración tenemos que hacer click en New Storage Account

image 

Lo que nos lleva a completar un sencillo formulario donde se nos pide un identificador único, región en la que queremos crear el espacio de almacenamiento y grupo de afinidad en caso de que queramos crearlo o unirnos a uno.

image

Una vez rellenamos el formulario, esta todo preparado, nos aparece en un listado y a la derecha encontramos todos los valores que vamos a necesitar desde nuestra aplicación.

image

El modelo de tablas

Llevamos muchos años trabajando con el modelo relacional, de modo que en cuanto alguien nos menciona una tabla, inmediatamente pasamos a pensar en un modelo entidad-relación.

Las tablas de Windows Azure Storage funcionan de un modo diferente, cada tabla esta formada por una serie de entidades (filas)y cada una de estas entidades tiene una serie de propiedades (columnas)

image

De modo que no hay un esquema determinado, dos entidades iguales, pueden tener diferentes número y tipo de columnas (propiedades). En caso de querer asegurar un esquema, ha de ser en el lado de la aplicación, por ejemplo con una clase que sirva como modelo de datos y que usemos para persistir la información.

 

A tener en cuenta…

Las tablas tienen una serie de campos obligatorios que tenemos que tener en consideración, especialmente el RowKey y el PartitionKey. El PartitionKey es la primera propiedad de una entidad, el sistema la utiliza para distribuir la información entre nodos. El RowKey, es la segunda propiedad de la entidad, es el identificador único de la entidad dentro de la partición.

Ejemplos:

RowKey ( Documento Aprobación ) Partition Key (v1, v1.1, v1.2) RowKey ( Clientes ) Partition Key ( 2345, 1256, 5678) RowKey ( Pedidos ) Partition Key (000121314, 555646448, 7895432)

El rowkey podemos decir que actúa como una especie de índice una vez estamos en el partition key adecuado.

 

Ejemplo de Storage Tables

 

Preparando el proyecto

Para el ejemplo, supongamos que partimos de un nuevo proyecto de tipo ASP.NET WebForms, con una página default.aspx.

Es importante añadir la referencia al assembly de trabajo con el storage. En el directorio ref de la instalación del Windows Azure SDK encontraremos el Microsoft.WindowsAzure.StorageClient.dll. Este assembly nos provee de un API que nos abstrae de las llamadas REST y nos permite trabajar directamente contra clases .NET.

 

El modelo de datos

Añadamos una clase Cliente.cs al proyecto, esta clase va a ser nuestro esquema, hemos de recordar que además de las propiedades que nosotros queramos, por el hecho de trabajar con el storage hemos de incluir algunas más (partitionKey, Rowkey, timestamp…) y decorar la clase con un atributo. Para evitarnos trabajo extr y simplificarlo, vamos a derivar de la clase TableServiceEntity que ya incluye todo lo necesario.

using System.Data.Services.Client; using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.StorageClient; using System.Data.Services.Common;

public class Cliente : TableServiceEntity {     public string Nombre { get; set; }     public string Apellidos { get; set; }     public string FechaNacimiento { get; set; }     public string Email { get; set; }

        public Cliente( )     {         this.PartitionKey = "Banca";         this.RowKey = Guid.NewGuid().ToString();

    } }

Tal y como lo hemos planteado para el ejemplo, vamos a agrupar (PartitionKey) los clientes por una segmentación basada en el tipo de cliente (no hemos dado opción a escoger y los estamos almacenando todos como ‘Banca’) y el identificador de cada cliente dentro del grupo (RowKey) va a ser un Guid (podría ser el contrato del cliente, el teléfono, mail, …).

 

El Contexto para los datos

Para poder trabajar de forma fácil con las entidades (almacenar, recuperar..) vamos a añadir una clase que deriva de TableServiceContext ( que a su vez deriva del DataServiceContext de WCF)

using System.Data.Services.Client; using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.StorageClient; using System.Linq;

public class TablaClientesContext : TableServiceContext {     public TablaClientesContext(string baseAddress, StorageCredentials credentials)             : base(baseAddress, credentials)         {         }

        public IQueryable<Cliente> Clientes         {             get             {                 return this.CreateQuery<Cliente>("Clientes");             }         }

        public void AddCliente(string nombre, string apellidos, string email, string fnac)         {             this.AddObject("Clientes", new Cliente(){ Nombre = nombre, Apellidos= apellidos, Email = email, FechaNacimiento = fnac});             this.SaveChanges();         }     }

Y por último, en default.aspx.nos construimos un formulario para poder recoger los parámetros del Cliente

<body>     <form id="form1" runat="server">     <div>         <p> Nombre</p>    <asp:TextBox ID="tbNombre" runat="server" />         <p> Apellidos</p>    <asp:TextBox ID="tbApellidos" runat="server" />         <p> Fecha Nac</p>    <asp:TextBox ID="tbFechaNac" runat="server" />         <p> Email</p>    <asp:TextBox ID="TbEmail" runat="server" />     </div>     <asp:Button ID="bSubmit" Text="guardar" runat="server"         onclick="bSubmit_Click" />     </form>

 

Conectar con el servicio

Vamos a ejecutar el alta del Cliente en el onclick del botón. Como estamos trabajando contra el entorno de desarrollo local, directamente cargaremos las credenciales del método CloudStorageAccount.DevelopmentStorageAccount; Y simplemente tenemos que instanciar la cuenta, el contexto y añadir los valores.

var cloudAccount = CloudStorageAccount.DevelopmentStorageAccount; var cloudTableClient = CloudStorageAccountStorageClientExtensions.CreateCloudTableClient(cloudAccount); cloudTableClient.CreateTableIfNotExist("Clientes");

var tableServiceContext = new TablaClientesContext(cloudAccount.TableEndpoint.ToString(),                                                     cloudAccount.Credentials);

tableServiceContext.AddCliente(tbNombre.Text, tbApellidos.Text, TbEmail.Text, tbFechaNac.Text);              

 

Probando Probando…

Como estamos en un proyecto clásico de Web, el simulador no va a arrancar el sólo (con los proyectos de tipo Cloud sí), tendremos que ir a la carpeta del SDK de Azure (C:\Program Files\Windows Azure SDK\v1.4\bin\devstore) y ejecutar manualmente DSService.exe.

Como no hemos puesto una etiqueta/label para reflejar errores ni resultados satisfactorios, vamos a comprobar directamente el resultado en la base de datos, es muy fácil a través del SQL Server Management Studio, queda a decisión del lector el complementar el ejemplo.

image

image

image

 

Tu turno… ¡el Reto! – Buscar y Borrar

En este post tienes el código para conectar con el servicio y dar de alta elementos… sólo falta que podamos consultarlos y darlos de baja. Te proponemos que complementes la aplicación para poder hacer búsquedas de clientes tanto por RowId como por alguna de sus propiedades y también habilitar la baja de clientes.

Pistas: Linq trabaja con IQueryable. También en el Training Kit de Windows Azure se pueden encontrar ejemplos…

Si tienes una suscripción de Windows Azure también puedes intentar trabajar directamente contra tu servicio en el cloud… pero tendrás que modificar la forma de conectarse al servicio ;)

Recursos para curiosos: SQL Azure vs Table Storage

Solución: En aproximadamente una semana enlazaremos la solución desde este post (y publicaremos un nuevo artículo/reto).

No dudéis en dejar comentarios, dudas … en este post, estaremos monitorizándolo para responder cuanto antes.

Happy Hacking!

David Salgado – @davidsb – Technology Evangelist