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);

view raw
CombinedFilter.cs
hosted with ❤ by GitHub

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);

view raw
SelectNombres.cs
hosted with ❤ by GitHub

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);

view raw
FullTableQuery.cs
hosted with ❤ by GitHub

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.

Responder

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. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s

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