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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()
:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
query.Take(10); |
Combinando todo
Por supuesto, podemos combinar todas estas funciones:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.