

 适用于 .NET 的 AWS SDK V3 已进入维护模式。

我们建议您迁移到 [适用于 .NET 的 AWS SDK V4](https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/welcome.html)。有关如何迁移的更多详细信息和信息，请参阅我们的[维护模式公告](https://aws.amazon.com/blogs/developer/aws-sdk-for-net-v3-maintenance-mode-announcement/)。

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 分页器
<a name="paginators"></a>

某些 AWS 服务会收集和存储大量数据，您可以使用适用于 .NET 的 AWS SDK的 API 调用来检索这些数据。如果您要检索的数据量变得太大，无法进行单个 API 调用，则可以通过使用*分页*将结果分成更易于管理的多个部分。

为了使您能够执行分页，开发工具包中许多服务客户端的请求和响应对象都提供了*延续令牌*（通常名为 `NextToken`）。其中一些服务客户端还提供了“分页工具”****。

分页工具使您能够避免延续令牌的开销，这可能涉及循环、状态变量、多个 API 调用等。使用分页工具时，您可以通过一行代码（`foreach` 循环的声明）从 AWS 服务中检索数据。如果需要多个 API 调用来检索数据，则分页工具会为您处理。

## 我在哪里可以找到分页工具？
<a name="paginators-find-them"></a>

并非所有服务都提供分页工具。确定服务是否为特定 API 提供分页工具的一种方法是在[适用于 .NET 的 AWS SDK API 参考](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/)中查看服务客户端类的定义。

例如，如果您查看 [AmazonCloudWatchLogsClient](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CloudWatchLogs/TCloudWatchLogsClient.html) 类的定义，就会看到一个 `Paginators` 属性。该属性为 Amazon CloudWatch Logs 提供了分页工具。

## 分页工具能提供什么好处？
<a name="paginators-use-them"></a>

分页工具包含让您能够查看完整响应的属性。它们通常还包含一个或多个属性，使您可以访问响应中最有趣的部分，我们将其称为*关键结果*。

例如，在前面提到的 `AmazonCloudWatchLogsClient` 中，`Paginator` 对象包含一个 `Responses` 属性，其中包含来自 API 调用的完整 DescribeLogGroupsResponse 对象。此 `Responses` 属性包含日志组集合等内容。

Paginator 对象还包含一个名为 `LogGroups` 的关键结果。此属性仅包含响应的日志组部分。有了这个关键结果，您就能在许多情况下减少和简化代码。

## 同步分页与异步分页
<a name="paginators-sync-async"></a>

分页工具提供同步和异步分页机制。.NET Framework 4.7.2（或更高版本）项目中支持同步分页。异步分页可在 .NET Core 项目（.NET Core 3.1、.NET 5 等）中使用。

由于建议使用异步操作和 .NET Core，因此接下来的示例向您展示了异步分页。[分页工具的其它注意事项](#paginators-additional)中的示例后面显示了有关如何使用同步分页和 .NET Framework 4.7.2（或更高版本）执行相同任务的信息。

## 示例
<a name="paginators-example"></a>

以下示例为您展示了如何使用适用于 .NET 的 AWS SDK显示日志组列表。相比之下，该示例说明如何使用和不使用分页工具执行该操作。在查看完整代码（稍后所示）之前，请考虑以下片段。

**在不使用分页工具的情况下获取 CloudWatch 日志组**

```
      // Loop as many times as needed to get all the log groups
      var request = new DescribeLogGroupsRequest{Limit = LogGroupLimit};
      do
      {
        Console.WriteLine($"Getting up to {LogGroupLimit} log groups...");
        var response = await cwClient.DescribeLogGroupsAsync(request);
        foreach(var logGroup in response.LogGroups)
        {
          Console.WriteLine($"{logGroup.LogGroupName}");
        }
        request.NextToken = response.NextToken;
      } while(!string.IsNullOrEmpty(request.NextToken));
```

**使用分页工具获取 CloudWatch 日志组**

```
      // No need to loop to get all the log groups--the SDK does it for us behind the scenes
      var paginatorForLogGroups =
        cwClient.Paginators.DescribeLogGroups(new DescribeLogGroupsRequest());
      await foreach(var logGroup in paginatorForLogGroups.LogGroups)
      {
        Console.WriteLine(logGroup.LogGroupName);
      }
```

这两个片段的结果完全相同，因此可以清楚地看到使用分页工具的好处。

**注意**  
在尝试构建和运行完整代码之前，请确保已[设置环境和项目](net-dg-config.md)。  
您可能还需要 [Microsoft.Bcl.AsyncInterfaces](https://www.nuget.org/packages/Microsoft.Bcl.AsyncInterfaces/) NuGet 程序包，因为异步分页工具使用 `IAsyncEnumerable` 接口。

### 完整代码
<a name="paginators-complete-code"></a>

本部分显示了本示例的相关参考和完整代码。

#### SDK 参考
<a name="w2aac11c15c23c19b5b1"></a>

NuGet 程序包：
+ [AWSSDK.CloudWatch](https://www.nuget.org/packages/AWSSDK.CloudWatch)

编程元素：
+ 命名空间 [Amazon.CloudWatch](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CloudWatch/NCloudWatch.html)

  类 [AmazonCloudWatchLogsClient](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CloudWatchLogs/TCloudWatchLogsClient.html)
+ 命名空间 [Amazon.CloudWatchLogs.Model](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CloudWatchLogs/NCloudWatchLogsModel.html)

  类 [DescribeLogGroupsRequest](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CloudWatchLogs/TDescribeLogGroupsRequest.html)

  类 [DescribeLogGroupsResponse](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CloudWatchLogs/TDescribeLogGroupsResponse.html)

  类 [LogGroup](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CloudWatchLogs/TLogGroup.html)

#### 完整代码
<a name="w2aac11c15c23c19b7b1"></a>

```
using System;
using System.Threading.Tasks;
using Amazon.CloudWatchLogs;
using Amazon.CloudWatchLogs.Model;

namespace CWGetLogGroups
{
  class Program
  {
    // A small limit for demonstration purposes
    private const int LogGroupLimit = 3;

    //
    // Main method
    static async Task Main(string[] args)
    {
      var cwClient = new AmazonCloudWatchLogsClient();
      await DisplayLogGroupsWithoutPaginators(cwClient);
      await DisplayLogGroupsWithPaginators(cwClient);
    }


    //
    // Method to get CloudWatch log groups without paginators
    private static async Task DisplayLogGroupsWithoutPaginators(IAmazonCloudWatchLogs cwClient)
    {
      Console.WriteLine("\nGetting list of CloudWatch log groups without using paginators...");
      Console.WriteLine("------------------------------------------------------------------");

      // Loop as many times as needed to get all the log groups
      var request = new DescribeLogGroupsRequest{Limit = LogGroupLimit};
      do
      {
        Console.WriteLine($"Getting up to {LogGroupLimit} log groups...");
        DescribeLogGroupsResponse response = await cwClient.DescribeLogGroupsAsync(request);
        foreach(LogGroup logGroup in response.LogGroups)
        {
          Console.WriteLine($"{logGroup.LogGroupName}");
        }
        request.NextToken = response.NextToken;
      } while(!string.IsNullOrEmpty(request.NextToken));
    }


    //
    // Method to get CloudWatch log groups by using paginators
    private static async Task DisplayLogGroupsWithPaginators(IAmazonCloudWatchLogs cwClient)
    {
      Console.WriteLine("\nGetting list of CloudWatch log groups by using paginators...");
      Console.WriteLine("-------------------------------------------------------------");

      // Access the key results; i.e., the log groups
      // No need to loop to get all the log groups--the SDK does it for us behind the scenes
      Console.WriteLine("\nFrom the key results...");
      Console.WriteLine("------------------------");
      IDescribeLogGroupsPaginator paginatorForLogGroups =
        cwClient.Paginators.DescribeLogGroups(new DescribeLogGroupsRequest());
      await foreach(LogGroup logGroup in paginatorForLogGroups.LogGroups)
      {
        Console.WriteLine(logGroup.LogGroupName);
      }

      // Access the full response
      // Create a new paginator, do NOT reuse the one from above
      Console.WriteLine("\nFrom the full response...");
      Console.WriteLine("--------------------------");
      IDescribeLogGroupsPaginator paginatorForResponses =
        cwClient.Paginators.DescribeLogGroups(new DescribeLogGroupsRequest());
      await foreach(DescribeLogGroupsResponse response in paginatorForResponses.Responses)
      {
        Console.WriteLine($"Content length: {response.ContentLength}");
        Console.WriteLine($"HTTP result: {response.HttpStatusCode}");
        Console.WriteLine($"Metadata: {response.ResponseMetadata}");
        Console.WriteLine("Log groups:");
        foreach(LogGroup logGroup in response.LogGroups) 
        {
          Console.WriteLine($"\t{logGroup.LogGroupName}");
        }
      }
    }
  }
}
```

## 分页工具的其它注意事项
<a name="paginators-additional"></a>
+ **分页工具不能多次使用**

  如果您需要在代码的多个位置显示特定 AWS 分页工具的结果，则不得多次使用分页工具对象。相反，每次需要时都要创建一个新的分页工具。这个概念如 `DisplayLogGroupsWithPaginators` 方法前面的示例代码中所示。
+ **同步分页**

  同步分页适用于 .NET Framework 4.7.2（或更高版本）的项目。
**警告**  
自 2024 年 8 月 15 日起，适用于 .NET 的 AWS SDK 将终止对 .NET Framework 3.5 的支持，并将支持的 .NET Framework 最低版本更改为 4.7.2。有关更多信息，请参阅博客文章 [Important changes coming for .NET Framework 3.5 and 4.5 targets of the 适用于 .NET 的 AWS SDK](https://aws.amazon.com/blogs/developer/important-changes-coming-for-net-framework-3-5-and-4-5-targets-of-the-aws-sdk-for-net/)。

  要查看此内容，请创建一个 .NET Framework 4.7.2（或更高版本）项目，然后将前面的代码复制到该项目中。然后只需将 `await` 关键字从两个 `foreach` 分页工具调用中移除，如以下示例所示。

  ```
  /*await*/ foreach(var logGroup in paginatorForLogGroups.LogGroups)
  {
    Console.WriteLine(logGroup.LogGroupName);
  }
  ```

  生成并运行该项目，以查看与异步分页相同的结果。