How to execute an Azure table storage query async? client version 4.0.1

C#Azure StorageAzure Table-Storage

C# Problem Overview


Want to execute queries Async on Azure Storage Client Version 4.0.1

There is NO method ExecuteQueryAsync()..

I am missing something? Should we continue to use the ExecuteQuerySegmentedAsync still? Thanks.

C# Solutions


Solution 1 - C#

I end up making an extension method to use ExecuteQuerySegmentedAsync. I am not sure whether this solution is optimal, if anybody has any comment please don’t hesitate.

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

Solution 2 - C#

When table query contains take clause specified solution will return more items than requested by query. Small change of while expression will solve that problem.

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

EDITED: Thanks to a suggestion from PaulG, corrected the issue with result count when query contains take clause and ExecuteQuerySegmentedAsync returns items in several passes.

Solution 3 - C#

This is in addition on to @JoseCh.'s answer.

Here is an extension method which allows you to specify an 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;
     }
}

It can be used if you only want to return the result set of a single column in storage:

// 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()

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJose Ch.View Question on Stackoverflow
Solution 1 - C#Jose Ch.View Answer on Stackoverflow
Solution 2 - C#DavorView Answer on Stackoverflow
Solution 3 - C#ZzeView Answer on Stackoverflow