Azure-cosmos-dotnet-v2: DocumentClient missing CreateDocumentQueryAsync

Created on 21 Jun 2017  路  8Comments  路  Source: Azure/azure-cosmos-dotnet-v2

The DocumentClient class has ReadDocumentAsync and CreateDocumentAsync, but lacks CreateDocumentQueryAsync.

As a workaround, I'm wrapping CreateDocumentQuery in Task.Run to ensure that it doesn't block the main thread.

Example

readonly DocumentClient client = new DocumentClient(new Uri(DocumentDbConstants.Url), DocumentDbConstants.PrimaryKey);

public Task<List<PersonModel>> GetAllPersonModels()
{
    return Task.Run(() => client.CreateDocumentQuery<PersonModel>(_documentCollectionUri).ToList());
}

Most helpful comment

Any progress on this one? I am curious why there is no async read query for documents.

All 8 comments

@brminnick We do have async version of the Query APIs that you can use to run the queries in async fashion life other CRUD APIs.

Note that instantiating CreateDocumentQuery doesn't executes any query. It's the calling of ToList in above example that executes the query. This is the blocking way for executing the query. If you want to execute the query in async fashion, use the following code:

var personModels = new List<PersonModel>();

var queryable = client.CreateDocumentQuery<PersonModel>(_documentCollectionUri, query).AsDocumentQuery();

while(queryable.HasMoreResults)
{
    var response = await queryable.ExecuteNextAsync<PersonModel>();
    personModels.AddRange(response);
}

Let me know if that helps!

Thanks @rnagpal

Can we change the name of ToList() to ToListAsync()? If the ToList() method is executing the query and performing an HttpClient task, it should be awaitable and include "Async" in the method name to follow best-practices.

The example above works, but it makes for an inconsistent API. I am new to DocumentDb and NoSQL, but it seems strange that the API is drastically different for Deleting a Document / Creating a Document / Getting One Document versus Getting All Documents (example below).

        public static Task<List<PersonModel>> GetAllPersonModelsAsync()
        {
            return Task.Run(() => client.CreateDocumentQuery<PersonModel>(_documentCollectionUri).ToList());
        }

        public static async Task<PersonModel> GetPersonModelAsync(string id)
        {
            var result = await client.ReadDocumentAsync<PersonModel>(CreateDocumentUri(id));

            return result;
        }

        public static async Task<PersonModel> CreatePersonModelAsync(PersonModel person)
        {
            var result = await client.CreateDocumentAsync(_documentCollectionUri, person);

            return (PersonModel)result.Resource;
        }

        public static async Task<HttpStatusCode> DeletePersonModel(string id)
        {
            var result = await client.DeleteDocumentAsync(CreateDocumentUri(id));

            return result.StatusCode;
        }

Similar to @rnagpal comment I've created ToListAsync extensions

public static async Task<List<T>> ToListAsync<T>(this IDocumentQuery<T> queryable) { var list = new List<T>(); while (queryable.HasMoreResults) { //Note that ExecuteNextAsync can return many records in each call var response = await queryable.ExecuteNextAsync<T>(); list.AddRange(response); } return list; } public static async Task<List<T>> ToListAsync<T>(this IQueryable<T> query) { return await query.AsDocumentQuery().ToListAsync(); }

How does one do a CountAsync() in this way?

ExecuteNextAsync will return all results (though paged) and if you limit it the Count property will be modified.

Thanks @michael-freidgeim-webjet

We can optimize ToListAsync by removing the async operator and returning the Task. This prevents the overhead that the compiler generates when using async.

public static Task<List<T>> ToListAsync<T>(this IQueryable<T> query) => query.AsDocumentQuery().ToListAsync();

public static async Task<List<T>> ToListAsync<T>(this IDocumentQuery<T> queryable)
{
    var list = new List<T>();

    while (queryable.HasMoreResults)
    {   
        //Note that ExecuteNextAsync can return many records in each call
        var response = await queryable.ExecuteNextAsync<T>();
        list.AddRange(response);
    }

    return list;
}


Any progress on this one? I am curious why there is no async read query for documents.

@brminnick We do have async version of the Query APIs that you can use to run the queries in async fashion life other CRUD APIs.

Note that instantiating CreateDocumentQuery doesn't executes any query. It's the calling of ToList in above example that executes the query. This is the blocking way for executing the query. If you want to execute the query in async fashion, use the following code:

var personModels = new List<PersonModel>();

var queryable = client.CreateDocumentQuery<PersonModel>(_documentCollectionUri, query).AsDocumentQuery();

while(queryable.HasMoreResults)
{
  var response = await queryable.ExecuteNextAsync<PersonModel>();
  personModels.AddRange(response);
}

Let me know if that helps!

It does not work when calling the function without type.

client.CreateDocumentQuery(_documentCollectionUri, query).AsDocumentQuery();

AsDocumentQuery() not exist.

I tried running this code according to your sample and can't get it to work. There's no .Where or .AsEnumerable(), according to your documentation this API is not obsolete? I can't seem to find any working example of how to query a single record with cosmo db SDK for c#. I'm using DocumentDB.Core version 2.2

Sample Code: SalesOrder querySalesOrder = client.CreateDocumentQuery(collectionLink)
.Where(so => so.AccountNumber == "10-4020-000510")
.AsEnumerable()
.FirstOrDefault();

Documentation:
https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.documents.client.documentclient.createdocumentquery?view=azure-dotnet#Microsoft_Azure_Documents_Client_DocumentClient_CreateDocumentQuery_System_String_Microsoft_Azure_Documents_SqlQuerySpec_Microsoft_Azure_Documents_Client_FeedOptions_System_Object

Sample Code Source:
(https://github.com/Azure/azure-cosmos-dotnet-v2/blob/f374cc601f4cf08d11c88f0c3fa7dcefaf7ecfe8/samples/code-samples/DocumentManagement/Program.cs#L248-L251) an

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Frankwayne picture Frankwayne  路  3Comments

cgelon picture cgelon  路  7Comments

ryancole picture ryancole  路  6Comments

Yonisha picture Yonisha  路  5Comments

ChristopherHaws picture ChristopherHaws  路  4Comments