

 AWS SDK for .NET V3 がメンテナンスモードになりました。

[AWS SDK for .NET 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 サービスでは大量のデータを収集して格納します。このデータは、AWS SDK for .NET の API コールを使用して取得できます。取得するデータ量が 1 回の API コールとしては多すぎる場合、*ページ分割*を使用して、より管理しやすい大きさに結果を分割できます。

ページ分割を実行するには、SDK 内の多くのサービスクライアントのリクエストオブジェクトとレスポンスオブジェクトによって提供される **継続トークン (通常は `NextToken`) を使用します。また、このようなサービスクライアントの一部では、****ページネーターも使用できます。

ページネーターを使用することで、ループ、状態変数、複数の API コールなどが影響を受ける場合がある継続トークンのオーバーヘッドを回避できます。ページネーターを使用すると、1 行のコード、すなわち `foreach` ループの宣言によって AWS からデータを取得できます。データを取得するために複数の API コールが必要な場合は、ページネーターがこれを処理します。

## ページネーターの使用の可否
<a name="paginators-find-them"></a>

すべてのサービスでページネーターを使用できるわけではありません。サービスで特定の API 向けのページネーターを提供しているかどうかを判断する 1 つの方法は、[AWS SDK for .NET 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>

ページネーターには、完全なレスポンスを表示するプロパティが含まれています。また、通常、主な結果であるレスポンスの最も興味深い部分へのアクセスを有効にする 1 つ以上のプロパティも含まれています。**。

たとえば、前述の `AmazonCloudWatchLogsClient` では、`Paginator` オブジェクトに `Responses` プロパティと、API コールによる完全な [DescribeLogGroupsResponse](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CloudWatchLogs/TDescribeLogGroupsResponse.html) オブジェクトが含まれています。特に、この `Responses` プロパティには、ロググループのコレクションが含まれています。

また、ページネーターオブジェクトにも、`LogGroups` という名前の主な結果が 1 つ含まれています。このプロパティにはレスポンスのロググループ部分のみが格納されています。この主な結果が含まれていることで、多くの状況でコードを減らして簡素化できます。

## 同期と非同期のページ分割
<a name="paginators-sync-async"></a>

ページネーターでは、ページ分割の同期と非同期の両方の仕組みを利用できます。.NET Framework 4.7.2 (またはそれ以降) のプロジェクトでは、同期ページ分割を使用できます。非同期ページ分割は、.NET Core プロジェクト (.NET Core 3.1、.NET 5 など) で使用できます。

非同期操作と.NET Core が推奨されているため、次の例では非同期ページ分割について説明します。同期ページネーションと.NET Framework 4.7.2 (またはそれ以降) を使用して同じタスクを実行する方法については、例の後の [ページネーターに関する追加の考慮事項](#paginators-additional) で説明します。

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

次の例では、AWS SDK for .NET を使用してロググループのリストを表示する方法を示します。比較のために、この例では、ペジネーターを使用した方法と、使用しない方法の両方を示します。後で示す完全なコードを確認する前に、次のスニペットを検討してください。

**ページネーターを使用せずに 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);
      }
```

これら 2 つのスニペットの結果はまったく同じであるため、ページネータを使用する利点が明確になります。

**注記**  
完全なコードをビルドして実行する前に、[環境とプロジェクトがセットアップされている](net-dg-config.md)ことを確認してください。  
非同期ページネーターでは `IAsyncEnumerable` インターフェイスが使用されるため、[Microsoft.Bcl.AsyncInterfaces](https://www.nuget.org/packages/Microsoft.Bcl.AsyncInterfaces/) NuGet パッケージが必要となる場合もあります。

### コード全文
<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 日以降、AWS SDK for .NETは .NET Framework 3.5 のサポートを終了し、.NET Framework の最小バージョンを 4.7.2 に変更します。詳細については、ブログ記事「[Important changes coming for .NET Framework 3.5 and 4.5 targets of the AWS SDK for .NET](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 (またはそれ以降) のプロジェクトを作成して、上記のコードをコピーします。次に、次の例に示すように、2 つの `foreach` ページネータコールから `await` キーワードのみを削除します。

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

  プロジェクトをビルドして実行し、非同期ページ分割の結果と同じ結果が生成されることを確認します。