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); | |
} |
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; | |
} |
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")); |
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); |
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.
Actualización: cambio de uso de código preformateado por Gists.