Haciendo consultas sobre Azure Table Storage

En las primeras versiones del Azure Storage library (1.x), la experiencia era muy similar a la de un Entity Repository, en el sentido que teníamos un Context y muchos llamados LINQ. Aunque era fácil de entender, era muy complicado determinar exactamente cuándo se hacía la consulta al servicio. Y era bastante molesto estar limitado solamente a las funciones «Where», «First» y «Select» de LINQ.

Desde la versión 2.0, tenemos disponible un objeto TableQuery que nos da más control sobre nuestra consulta y podemos entender mejor qué está pasando.

Trayendo una entidad

Para traer una entidad necesitamos hacer una consulta con el Partition Key y el Row Key.

Lo primero que vamos a necesitar es de nuestro account:


using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.Storage;
public static CloudStorageAccount GetAccount()
{
const string configName = "AccountKeyEnConfig";
string value = RoleEnvironment.GetConfigurationSettingValue(configName);
return CloudStorageAccount.Parse(value);
}

view raw

GetAccount.cs

hosted with ❤ by GitHub

Luego, hacemos nuestra consulta:


using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
public object GetEntity(string partitionKey, string rowKey)
{
CloudStorageAccount account = GetAccount();
CloudTableClient cloudTableClient = account.CreateCloudTableClient();
CloudTable table = cloudTableClient.GetTableReference("NombreDeLaTabla");
TableOperation retrieveOperation = TableOperation.Retrieve(partitionKey, rowKey);
TableResult retrievedResult = table.Execute(retrieveOperation);
return retrievedResult.Result;
}

view raw

GetEntity.cs

hosted with ❤ by GitHub

Filtros

El Table Storage utiliza la interfaz de OData, que soporta algunas funciones básicas de consulta, como filter, top, select y orderby, y algunas más. La librería de Storage Client las expone a través de la clase TableQuery.

La clase TableQuery puede usarse para hacer consultas más complejas:


using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
TableQuery query = new TableQuery()
.Where(TableQuery.GenerateFilterCondition("Nombre", QueryComparisons.Equal, "Guillermo"));

view raw

WhereQuery.cs

hosted with ❤ by GitHub

Tenemos dos elementos importantes a tener en cuenta aquí: GenerateFilterCondition y QueryComparisons:

Hay algunas variaciones de GenerateFilterCondition, de acuerdo al tipo de datos, siendo este el usado para string:

GenerateFilterConditionForGuid
GenerateFilterConditionForLong
GenerateFilterConditionForDouble
GenerateFilterConditionForInt
GenerateFilterConditionForDate
GenerateFilterConditionForBool
GenerateFilterConditionForBinary

Las opciones de QueryComparisons disponibles son:

QueryComparisons.Equal
QueryComparisons.NotEqual
QueryComparisons.GreaterThan
QueryComparisons.LessThan
QueryComparisons.GreaterThanOrEqual
QueryComparisons.LessThanOrEqual

Si necesitamos combinar diferentes filtros, lo hacemos a través del método TableQuery.CombineFilters():


string filtro1 = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "Argentina");
string filtro2 = TableQuery.GenerateFilterCondition("Nombre", QueryComparisons.Equal, "Guillermo");
string filtroCombinado = TableQuery.CombineFilters(filtro1, TableOperators.And, filtro2);
TableQuery query = new TableQuery().Where(filtroCombinado);

Siendo los operadores:

TableOperators.And
TableOperators.Or
TableOperators.Not

Selects

Select nos permite traer específicamente el dato que estamos necesitando. Es una función que puede ser muy útil especialmente a aquellos que necesitan aprovechar al máximo el uso de red, como quienes trabajen con una aplicación WinRT.

Por ejemplo, para traer todos los nombres de nuestra tabla de Clientes:


CloudTable customerTable = tableClient.GetTableReference("clientes");
TableQuery query = new TableQuery().Select(new string[] { "Nombre" });
customerTable.ExecuteQuery(query);

Take

Si necesitamos limitar la cantidad de resultados, simplemente usamos:


query.Take(10);

view raw

Take.cs

hosted with ❤ by GitHub

Combinando todo

Por supuesto, podemos combinar todas estas funciones:


TableQuery query = new TableQuery()
.Where(TableQuery.GenerateFilterCondition("Nombre", QueryComparisons.Equal, "Guillermo"))
.Select(new string[] { "Email" })
.Take(5);

Consultas fuertemente tipadas

Las consultas de todos los ejemplos devuelven tipos dinámicos, pero también podemos hacer consultas que devuelvan el tipo de dato que necesitamos usando TableQuery<Cliente>.

Espero que les sea útil.

@gjbellmann

Actualización: cambio de uso de código preformateado por Gists.

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.