Compartir a través de


Windows Azure Table

El servicio de tablas de Windows Azure proporciona almacenamiento estructurado no relacional basado en tablas. Como todos los servicios de almacenamiento de Windows Azure proporciona un API REST.

En este caso el API REST de las tablas de Windows Azure sigue el contrato definido por ADO.NET Data Services, lo que proporciona una comodidad extra: es posible usar la librería cliente para ADO.NET Data Service para acceder a las tablas e incluso realizar consultas LINQ (con ciertas limitaciones) sobre las tablas de Windows Azure sin tener que trabajar directamente con REST. Es la librería cliente para ADO.NET Data Service quien se encarga de convertir las peticiones que haga la aplicación en las peticiones HTTP correspondientes.

Entidades y Tablas

Dentro de una cuenta de almacenamiento de Windows Azure es posible crear múltiples tablas. Las tablas se diferencian por su nombre.

Dentro de las tablas se almacenarán entidades. Las entidades se representan en C# o en VB.Net como clases que derivan de la clase TableServiceEntity y que tiene una serie de propiedades públicas que serán almacenadas en la tabla cuando los objetos sean persistidos.

A continuación puede verse como sería una entidad Visita que tiene las propiedades Nombre, Lugar y Descripción.

 public class VisitaEntity : TableServiceEntity 
{
public VisitaEntity() : base(Guid.NewGuid().ToString(), String.Empty)
{   }
 public VisitaEntity(string nombre, string lugar, string descripcion):
base(lugar, nombre)
{
Nombre = nombre;
Lugar = lugar;
Descripcion = descripcion;
}
public string Nombre
{
get;
set;
}
public string Lugar
{
get;
set;
}
public string Descripcion
{
get;
set;
}
}

Las entidades son, desde el punto de vista de Azure Storage son colecciones de pares propiedad - valor, similares a las filas de una tabla en una base de datos relacional. Todas las tablas y por tanto todas las entidades tiene dos propiedades que siempre deben aparecer y que identifican de manera unívoca al objeto y el lugar físico donde se almacena (partición).

La primera propiedad es la clave de la partición, PartitionKey, que identifica a que partición pertenece una entidad. La única garantía que existe sobre las particiones, es que, acceder a entidades almacenadas en la misma partición va a tener, típicamente, un menor coste que acceder a entidades en particiones diferentes.

Es importante poner cuidado a la hora de elegir la clave de partición de las entidades para asegurar que entidades que se acceden típicamente al mismo tiempo comparten la misma clave de partición. También es importante que las particiones sean homogéneas en tamaño. Por ejemplo, si se almacenan clientes, una posible clave de partición podría ser el código postal, si típicamente la aplicación trabaja con los clientes de un determinado código postal, por ejemplo para realizar estadísticas.

La segunda propiedad relevante es la clave de la entidad, EntityKey, que identifica de manera unívoca una entidad dentro de una partición.

La combinación de PartitionKey más EntityKey identifica de manera única una entidad de manera global. Sería el equivalente a una clave única compuesta en el mundo relacional.

A diferencia de las tablas de las bases de datos relacionales una tabla puede contener entidades que tengan diferente número de propiedades. Además no existen conceptos relacionados con la integridad referencial, será la aplicación la encargad de mantener esta integridad de los datos.

Lógicamente antes de poder almacenar datos en una tabla es necesario crearla si es que no existe, algo muy fácil gracias al API de Azure.

var storageAccount = CloudStorageAccount.FromConfigurationSetting
("DataConnectionString");
...  
storageAccount.CreateCloudTableClient().CreateTableIfNotExist
(DondeHasEstadoDataContext.VisitasTableName);

Contexto de acceso a datos

Otro concepto importante a la hora de trabajar con las tablas de Windows Azure es el contexto.

El contexto es una clase que deriva de TableContextService y es el objeto que permite, usando LINQ, acceder a las tablas almacenadas en la cuenta de almacenamiento de Azure. Al contexto será necesario indicarle la URL de acceso al sistema de almacenamiento,  URL que proporciona la plataforma Azure cuando se crea una cuenta de almacenamiento.

Esta es una típica clase de contexto de tabla:

 public class DondeHasEstadoDataContext : TableServiceContext
{
public const string VisitasTableName = "Visitas";
  public DondeHasEstadoDataContext(string baseAddress, StorageCredentials
credentials) : base(baseAddress, credentials)
{   }  
public IQueryable<VisitaEntity> VisitasTable
{
get
{
return this.CreateQuery<VisitaEntity>(VisitasTableName);
}
}
}

Las clases de contexto proporcionan acceso a las tablas mediante LINQ devolviendo una implementación de IQueryable para la clase concreta de nuestra entidad. Devolver un IQueryable va a permitir realizar consultas LINQ sobre una tabla.

Orígenes de datos

Por último, como siempre que se accede a datos, será necesario algún tipo de objeto que permita conectarse a la fuente de datos.

 Estos objetos en Windows Azure Storage se llaman por convención 'data sources' y se utilizan para implementar en un solo objeto todas las operaciones de acceso a datos que se realizarán sobre las entidades almacenadas en una tabla. Al contrario que las clases anteriores, esta clase no tiene por qué derivar de ninguna otra, tal y como se puede ver en la siguiente porción de código:

public class VisitasDataSource
{
private DondeHasEstadoDataContext _dataContext = null;
  public VisitasDataSource()
{
var storageAccount = CloudStorageAccount.FromConfigurationSetting
("DataConnectionString");
_dataContext = new DondeHasEstadoDataContext(storageAccount.
TableEndpoint.ToString(), storageAccount.Credentials);
storageAccount.CreateCloudTableClient().CreateTableIfNotExist
(DondeHasEstadoDataContext.VisitasTableName);
}
public IEnumerable<VisitaEntity>
Select()
{
var results = from v in _dataContext.VisitasTable select v;  
return results.AsTableServiceQuery< VisitaEntity>().Execute();
}  
public void Delete(VisitaEntity itemToDelete)
{
_dataContext.AttachTo(DondeHasEstadoDataContext.VisitasTableName,
itemToDelete, "*");
_dataContext.DeleteObject(itemToDelete);
_dataContext.SaveChanges();
}  
public void Insert(VisitaEntity newItem)
{
_dataContext.AddObject(DondeHasEstadoDataContext.VisitasTableName,
newItem);
_dataContext.SaveChanges();
}
}

La cadena de conexión

Otro aspecto fundamental siempre que se habla de acceso a datos es establecer la cadena de conexión. Lo mismo ocurre en el almacenamiento de Windows Azure.

El SDK de Windows Azure proporciona un entorno simulado del almacenamiento de Azure, el Windows Azure Development Storage que corre en la máquina de desarrollo sobre SQL Server Express.

Para conectarse al Azure Development Storage se puede establecer la siguiente entrada en la sección de cadenas de conexión del archivo de configuración de la aplicación:

<connectionStrings>
<add name="DataConnectionString" connectionString="UseDevelopment
Storage=true"/>
</connectionStrings>

Para obtener la cadena de conexión desde el código será tan simple como hacer:

 var storageAccount = CloudStorageAccount.FromConfigurationSetting
("DataConnectionString");
_dataContext = new DondeHasEstadoDataContext(storageAccount.TableEndpoint.
ToString(),storageAccount.Credentials)