web-dev-qa-db-fra.com

Comment exécuter une requête de stockage de table Azure asynchrone? version client 4.0.1

Vous souhaitez exécuter des requêtes Async sur Azure Storage Client version 4.0.1

Il n'y a AUCUNE méthode ExecuteQueryAsync () ..

Il me manque quelque chose? Devrions-nous continuer à utiliser ExecuteQuerySegmentedAsync? Merci.

56
Jose Ch.

Je finis par créer une méthode d'extension pour utiliser ExecuteQuerySegmentedAsync. Je ne sais pas si cette solution est optimale, si quelqu'un a un commentaire, n'hésitez pas.

public static async Task<IList<T>> ExecuteQueryAsync<T>(this CloudTable table, TableQuery<T> query, CancellationToken ct = default(CancellationToken), Action<IList<T>> onProgress = null) where T : ITableEntity, new()
    {

        var items = new List<T>();
        TableContinuationToken token = null;

        do
        {

            TableQuerySegment<T> seg = await table.ExecuteQuerySegmentedAsync<T>(query, token);
            token = seg.ContinuationToken;
            items.AddRange(seg);
            if (onProgress != null) onProgress(items);

        } while (token != null && !ct.IsCancellationRequested);

        return items;
    }
74
Jose Ch.

Lorsque la requête de table contient une clause de prise, la solution spécifiée renvoie plus d'éléments que requis par la requête. Un petit changement d'expression tandis que résoudra ce problème.

public static async Task<IList<T>> ExecuteQueryAsync<T>(this CloudTable table, TableQuery<T> query, CancellationToken ct = default(CancellationToken), Action<IList<T>> onProgress = null) where T : ITableEntity, new()
{
    var runningQuery = new TableQuery<T>()
    {
        FilterString = query.FilterString,
        SelectColumns = query.SelectColumns
    };

    var items = new List<T>();
    TableContinuationToken token = null;

    do
    {
        runningQuery.TakeCount = query.TakeCount - items.Count;

        TableQuerySegment<T> seg = await table.ExecuteQuerySegmentedAsync<T>(runningQuery, token);
        token = seg.ContinuationToken;
        items.AddRange(seg);
        if (onProgress != null) onProgress(items);

    } while (token != null && !ct.IsCancellationRequested && (query.TakeCount == null || items.Count < query.TakeCount.Value));

    return items;
}

MODIFIÉ : Grâce à une suggestion de PaulG, correction du problème avec le nombre de résultats lorsque la requête contient la clause take et ExecuteQuerySegmentedAsync renvoie des éléments en plusieurs passes.

14
Davor

C'est en plus de @JoseCh. réponse.

Voici une méthode d'extension qui vous permet de spécifier un EntityResolver:

public static async Task<IList<TResult>> ExecuteQueryAsync<T, TResult>(this CloudTable table, TableQuery query, EntityResolver<TResult> resolver, Action<IList<TResult>> onProgress = null, CancellationToken cancelToken = default(CancellationToken))
            where T : ITableEntity, new()
{
    var items = new List<TResult>();
    TableContinuationToken token = null;

    do
    {
        TableQuerySegment<TResult> seg = await table.ExecuteQuerySegmentedAsync(query: query, resolver: resolver, token: new TableContinuationToken(), cancellationToken: cancelToken).ConfigureAwait(false);
        token = seg.ContinuationToken;
        items.AddRange(seg);
        onProgress?.Invoke(items);
     }
     while (token != null && !cancelToken.IsCancellationRequested);
         return items;
     }
}

Il peut être utilisé si vous souhaitez uniquement renvoyer le jeu de résultats d'une seule colonne dans le stockage:

// maps to a column name in storage
string propertyName = nameof(example.Category);

// Define the query, and select only the Category property.
var projectionQuery = new TableQuery().Select(new string[] { propertyName });

// Define an entity resolver to work with the entity after retrieval.
EntityResolver<string> resolver = (pk, rk, ts, props, etag) => props.ContainsKey(propertyName) ? props[propertyName].StringValue : null;

var categories = (await someTable.ExecuteQueryAsync<DynamicTableEntity, string>(query: projectionQuery, resolver: resolver).ConfigureAwait(false)).ToList()
0
Zze