简体   繁体   中英

Cosmos DB and Azure functions Get item .net 5 Asynchrous foreach statement cannot operate on variable of type FeedIterator

Im trying to get an item from azure cosmos db in azure functions .net 5.0 but im getting this error because im using async method

Feedlterator <rsakeys> Container.GetitemQuerylterator <rsakeys> (QueryDefinition queryDefinition, [string continuation Token = null], [QueryRequestOptions requestOptions = null]) (+ 1 overload) This method creates a query for items under a container in an Azure Cosmos database using a SQL statement with parameterized values.  It returns a Feedlterator.  For more information on preparing SQL statements with parameterized values, please see QueryDefinition.  
Returns: 
An iterator to go through the items.  CS8411: Asynchronous foreach statement cannot operate on variables of type 'Feediterator <rsakeys>' because 'Feedlterator <rsakeys>' does not contain a suitable public instance or extension definition for 'GetAsyncEnumerator
CS8411: Asynchronous foreach statement cannot operate on variables of type 'Feediterator <rsakeys>' because 'Feedlterator <rsakeys>' does not contain a suitable public instance or extension definition for 'GetAsyncEnumerator

在此处输入图片说明

This is my code, i have not found any good documentation on this error at all, im pretty much lost.

namespace projectA
{
    class projectA
    {
        [Function("projectA")]
        async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Anonymous, "")] HttpRequestData req,
            FunctionContext context)
        {

            var logger = context.GetLogger("projectA");
            logger.LogInformation("C# HTTP trigger function processed a request.");
            response.Headers.Add("Content-Type", "text/plain; charset=utf-8");

            /// The Azure Cosmos DB endpoint.
            string EndpointUrl = "https://name.documents.azure.com:443/";

            /// The primary key for the Azure DocumentDB account.
            string PrimaryKey = "primarykey";

            // The Cosmos client instance
            CosmosClient cosmosClient = new CosmosClient(EndpointUrl, PrimaryKey);

            Database database;
            Container container;
            string databaseId = "database1";
            string containerId = "container1";

            var sqlQueryText = "SELECT * FROM c WHERE c.key = '123'";
            Console.WriteLine("Running query: {0}\n", sqlQueryText);
            container = cosmosClient.GetContainer(databaseId, containerId);
            QueryDefinition queryDefinition = new QueryDefinition(sqlQueryText);
 
            List<rsakeys> rsakeyss = new List<rsakeys>();
//In this await foreach i get the error...
                 await foreach (rsakeys RsaKeys in container.GetItemQueryIterator<rsakeys>(queryDefinition))
                {
                    rsakeyss.Add(RsaKeys);
                    Console.WriteLine("\tRead {0}\n", RsaKeys);
                }
            }
        }
    }    

The pattern you would use for a Feed Iterator would be

while (feedIterator.HasMoreResults)
   foreach (var item in await feedIterator.ReadNextAsync())
       Console.Write(item.Cost);

If you wanted to use an awaited foreach (AKA IAsynEnumerable ), you could roll your own IAsynEnumerable to yield

private static async IAsyncEnumerable<T> SomeMethod<T>(
   Container container,
   QueryDefinition queryDefinition,
   [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
   using var feedIterator = container.GetItemQueryIterator<T>(queryDefinition);
   while (feedIterator.HasMoreResults)
      foreach (var item in await feedIterator
              .ReadNextAsync(cancellationToken)
              .ConfigureAwait(false))
         yield return item;
}

Usage

await foreach(var item in SomeMethod<SomeType>(container, queryDefinition)
   Console.Write(item);

Bonus fact

It's also worth noting that ReadNextAsync returns Task<FeedResponse<T>>

public abstract Task<FeedResponse<T>> ReadNextAsync(CancellationToken cancellationToken = default);

FeedResponse is inherited from Response

FeedResponse<T> : Response<IEnumerable<T>>, IEnumerable<T>

However, for convenience Response has an implicit operator , so it can be implicitly converted to its generic Enumerbale type IEnumerable<T>

public static implicit operator T(Response<T> response)

Ergo, both of the following statements are valid

using var feedIterator = container.GetItemQueryIterator<Bob>(queryDefinition);

FeedResponse<Bob> bobResponse = await feedIterator.ReadNextAsync()

IEnumerable<Bob> bobs = await feedIterator.ReadNextAsync()

Update From comments

After doing using

var feedIterator = container.GetItemQueryIterator<rsakeys>(queryDefinition); var x = await feedIterator.ReadNextAsync(); Console.WriteLine(x.GetType().ToString());

I get this console output :

Microsoft.Azure.Cosmos.QueryResponse`1[PolarisRSAFunction1NET5.rsakeys]

how do i access the query value?

Calling ReadNextAsync would return an FeedResponse<rsakeys> from there you can just call x.Resource to return an IEnumerable<rsakeys> or just directly assign it

Ie

var response = await feedIterator.ReadNextAsync();
IEnumerable<rsakeys> items = response.Resource;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM