首页 > 解决方案 > Cosmos DB 和 Azure 函数 Get item .net 5 异步 foreach 语句无法对 FeedIterator 类型的变量进行操作

问题描述

我试图在 azure functions .net 5.0 中从 azure cosmos db 获取项目,但我收到此错误,因为我使用异步方法

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

在此处输入图像描述

这是我的代码,我根本没有找到任何关于这个错误的好的文档,我几乎迷路了。

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

标签: c#.netazureazure-functions

解决方案


您将用于Feed 迭代器的模式是

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

如果你想使用等待的 foreach (AKA IAsynEnumerable),你可以自己滚动IAsynEnumerable让出

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

用法

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

奖金事实

还值得注意的是,ReadNextAsync回报Task<FeedResponse<T>>

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

FeedResponse继承自Response

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

但是,为了方便起见,它Response有一个隐式运算符,因此可以将其隐式转换为其泛型 Enumerbale 类型IEnumerable<T>

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

因此,以下两个陈述都有效

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

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

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

从评论更新

使用后

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

我得到这个控制台输出:

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

我如何访问查询值?

调用ReadNextAsyncFeedResponse<rsakeys>从那里返回一个你可以调用x.Resource返回一个IEnumerable<rsakeys>或直接分配它

IE

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

推荐阅读