閱讀英文

共用方式為


使用 Azure SDK for .NET. 進行分頁

在本文中,您將了解如何使用 Azure SDK for .NET 分頁功能,以提升使用大型資料集的效率和生產力。 分頁是將大型資料集分割成頁面的動作,讓取用者更容易逐一查看較小的資料量。 從 C# 8 開始,您可以使用非同步 (async) 串流,以非同步方式建立和使用串流。 非同步串流是以 IAsyncEnumerable<T> 介面為基礎。 Azure SDK for .NET 會公開 IAsyncEnumerable<T> 的實作以及其 AsyncPageable<T> 類別。

本文中的所有範例都依賴以下 NuGet 套件:

如需 Azure SDK for .NET 套件的最新目錄,請參閱 Azure SDK 最新版本 (部分機器翻譯)。

可分頁傳回型別

從 Azure SDK for .NET 具現化的用戶端可以傳回以下可分頁類型。

類型 描述
Pageable<T> 在頁面中擷取的值集合
AsyncPageable<T> 以非同步方式在頁面中擷取的值集合

本文中的大多數範例都是非同步性質,使用 AsyncPageable<T> 類型的變體。 針對 I/O 繫結作業,我們非常建議使用非同步程式設計方法。 最佳使用案例是使用 Azure SDK for .NET 內的非同步 API,因為這些作業代表 HTTP/S 網路呼叫。

使用 await foreach 逐一查看 AsyncPageable

如要使用 await foreach 語法逐一查看 AsyncPageable<T>,請考慮以下範例:

C#
async Task IterateSecretsWithAwaitForeachAsync()
{
    AsyncPageable<SecretProperties> allSecrets = client.GetPropertiesOfSecretsAsync();

    await foreach (SecretProperties secret in allSecrets)
    {
        Console.WriteLine($"IterateSecretsWithAwaitForeachAsync: {secret.Name}");
    }
}

在上述 C# 程式碼中:

  • 系統會叫用 SecretClient.GetPropertiesOfSecretsAsync 方法並傳回 AsyncPageable<SecretProperties> 物件。
  • await foreach 迴圈中,會以非同步方式得出每一個 SecretProperties
  • 當每個 secret 材質化時,其 Name 也會寫入主控台。

使用 while 逐一查看 AsyncPageable

如要在 await foreach 語法不可用的情況下逐一查看 AsyncPageable<T>,請使用 while 迴圈。

C#
async Task IterateSecretsWithWhileLoopAsync()
{
    AsyncPageable<SecretProperties> allSecrets = client.GetPropertiesOfSecretsAsync();

    IAsyncEnumerator<SecretProperties> enumerator = allSecrets.GetAsyncEnumerator();
    try
    {
        while (await enumerator.MoveNextAsync())
        {
            SecretProperties secret = enumerator.Current;
            Console.WriteLine($"IterateSecretsWithWhileLoopAsync: {secret.Name}");
        }
    }
    finally
    {
        await enumerator.DisposeAsync();
    }
}

在上述 C# 程式碼中:

逐一查看 AsyncPageable 頁面

如果您想要控制從服務接收值的頁面,請使用 AsyncPageable<T>.AsPages 方法:

C#
async Task IterateSecretsAsPagesAsync()
{
    AsyncPageable<SecretProperties> allSecrets = client.GetPropertiesOfSecretsAsync();

    await foreach (Page<SecretProperties> page in allSecrets.AsPages())
    {
        foreach (SecretProperties secret in page.Values)
        {
            Console.WriteLine($"IterateSecretsAsPagesAsync: {secret.Name}");
        }

        // The continuation token that can be used in AsPages call to resume enumeration
        Console.WriteLine(page.ContinuationToken);
    }
}

在上述 C# 程式碼中:

搭配使用 System.Linq.AsyncAsyncPageable

System.Linq.Async 套件提供一組 LINQ 方法,能在 IAsyncEnumerable<T> 類型上運作。 因為 AsyncPageable<T> 會實作 IAsyncEnumerable<T>,所以您可以使用 System.Linq.Async 來查詢和轉換資料。

轉換為 List<T>

使用 ToListAsyncAsyncPageable<T> 轉換為 List<T>。 如果在單一頁面中未傳回資料,這個方法可能會進行數個服務呼叫。

C#
async Task ToListAsync()
{
    AsyncPageable<SecretProperties> allSecrets =
        client.GetPropertiesOfSecretsAsync();

    List<SecretProperties> secretList = await allSecrets.ToListAsync();

    secretList.ForEach(secret =>
        Console.WriteLine($"ToListAsync: {secret.Name}"));
}

在上述 C# 程式碼中:

  • 系統會叫用 SecretClient.GetPropertiesOfSecretsAsync 方法並傳回 AsyncPageable<SecretProperties> 物件。
  • 等候 ToListAsync 方法,以材質化新的 List<SecretProperties> 執行個體。

採用前 N 個元素

Take 只能用來取得 AsyncPageable 的前 N 個元素。 使用 Take 會進行所需的最少服務呼叫來取得 N 個項目。

C#
async Task TakeAsync(int count = 30)
{
    AsyncPageable<SecretProperties> allSecrets =
        client.GetPropertiesOfSecretsAsync();

    await foreach (SecretProperties secret in allSecrets.Take(count))
    {
        Console.WriteLine($"TakeAsync: {secret.Name}");
    }
}

其他方法

System.Linq.Async 提供其他方法,這些方法提供的功能等同於各自的同步Enumerable對應項。 這些方法的範例包括 SelectWhereOrderByGroupBy

注意用戶端評估

使用 System.Linq.Async 套件時,請注意 LINQ 作業會在用戶端上執行。 下列查詢會為了計算而擷取「所有」項目:

C#
// ⚠️ DON'T DO THIS! 😲
int expensiveSecretCount =
    await client.GetPropertiesOfSecretsAsync()
        .CountAsync();

警告

相同的警告適用於 Where 等運算子。 如果有的話,請一律偏好伺服器端篩選、匯總或投影資料。

作為可觀察的序列

System.Linq.Async 套件主要會用來在 IAsyncEnumerable<T> 序列上提供可觀察的模式功能。 非同步串流以提取為基礎。 逐一查看它們的項目時,會「提取」下一個可用的項目。 這個方法與以推送為基礎的觀察模式並列。 當項目變得可用時,會被「推送」到扮演觀察者角色的訂閱者。 System.Linq.Async 套件提供 ToObservable 擴充方法,可讓您將 IAsyncEnumerable<T> 轉換為 IObservable<T>

想像 IObserver<SecretProperties> 實作:

C#
sealed file class SecretPropertyObserver : IObserver<SecretProperties>
{
    public void OnCompleted() =>
        Console.WriteLine("Done observing secrets");

    public void OnError(Exception error) =>
        Console.WriteLine($"Error observing secrets: {error}");

    public void OnNext(SecretProperties secret) =>
        Console.WriteLine($"Observable: {secret.Name}");
}

您可以取用 ToObservable 擴充方法,如下所示:

C#
IDisposable UseTheToObservableMethod()
{
    AsyncPageable<SecretProperties> allSecrets =
        client.GetPropertiesOfSecretsAsync();

    IObservable<SecretProperties> observable = allSecrets.ToObservable();

    return observable.Subscribe(
        new SecretPropertyObserver());
}

在上述 C# 程式碼中:

  • 系統會叫用 SecretClient.GetPropertiesOfSecretsAsync 方法並傳回 AsyncPageable<SecretProperties> 物件。
  • 系統會在 AsyncPageable<SecretProperties> 執行個體上呼叫 ToObservable() 方法,傳回 IObservable<SecretProperties>
  • observable 會受到訂閱,傳遞進觀察者實作,並將訂閱傳回呼叫者。
  • 訂閱有 IDisposable 性質。 當訂閱受到處置後,便會結束。

逐一查看可分頁

Pageable<T>AsyncPageable<T> 的同步版本,可搭配一般的 foreach 迴圈使用。

C#
void IterateWithPageable()
{
    Pageable<SecretProperties> allSecrets = client.GetPropertiesOfSecrets();

    foreach (SecretProperties secret in allSecrets)
    {
        Console.WriteLine($"IterateWithPageable: {secret.Name}");
    }
}

重要

雖然此同步 API 可供使用,但請使用非同步 API 替代專案,以取得更好的體驗。

另請參閱