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.
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.
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;
}
ExecuteQuerySegmentedAsync
and combining the results from each segment). Your code looks good. The only suggestion I have is for you to, if possible, pre-allocate the items
list to a size that will be big enough to hold all the entities most of the time by using the constructor that accepts an integer. This will reduce the amount of resizing needed. –
Nephritis ct
(CancellationToken) into the ExecuteQuerySegmentedAsync
since this extensions doesn't use it anywhere else. I think @Jose Ch. forgot to add it, I tried to edit the post because ct is lower than 6 characters :< –
Phionna 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.
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()
© 2022 - 2024 — McMap. All rights reserved.