在本文中,您將瞭解如何使用適用於 .NET 的 Azure SDK 分頁功能,在大型數據集上有效率且具生產力地運作。 分頁是將大型數據集分割成頁面的動作,可讓取用者更輕鬆地逐一查看較小的數據量。 從 C# 8 開始,您可以使用 異步 (async) 數據流,以異步方式建立和使用數據流。 異步數據流是基於IAsyncEnumerable<T>介面的。 適用於 .NET 的 Azure SDK 會以其 IAsyncEnumerable<T>
類別公開 AsyncPageable<T>
的實作。
本文中的所有範例都依賴下列 NuGet 套件:
- Azure.Security.KeyVault.Secrets
- Microsoft.Extensions.Azure
- Microsoft.Extensions.Hosting
- System.Linq.Async
如需適用於 .NET 套件的 Azure SDK 最新目錄,請參閱 Azure SDK 最新版本。
可分頁傳回類型
從 Azure SDK for .NET 實例化的用戶端可以傳回下列可分頁類型。
類型 | 說明 |
---|---|
Pageable<T> |
在頁面中擷取的值集合 |
AsyncPageable<T> |
以異步方式在頁面中擷取的值集合 |
本文中的大部分範例都是使用 AsyncPageable<T>
類型的不同變化方式來實現異步的。 針對 I/O 系結作業使用異步程式設計是理想的方式。 完美的使用案例是使用適用於 .NET 的 Azure SDK 異步 API,因為這些作業代表 HTTP/S 網路呼叫。
逐一迭代AsyncPageable
使用await foreach
若要使用 AsyncPageable<T>
語法遍歷 await foreach
,請參考以下範例:
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
會寫入主控台。
逐一迭代AsyncPageable
使用while
若要在無法使用 AsyncPageable<T>
語法時,使用 await foreach
迴圈來遍歷 while
。
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# 程式碼中:
-
SecretClient.GetPropertiesOfSecretsAsync 方法被調用,並返回
AsyncPageable<SecretProperties>
物件。 - 會叫用AsyncPageable<T>.GetAsyncEnumerator方法,並傳回
IAsyncEnumerator<SecretProperties>
。 - 方法 MoveNextAsync() 會重複叫用,直到沒有要傳回的項目為止。
逐一 AsyncPageable
瀏覽頁面
如果您想要控制從服務接收值頁面,請使用 AsyncPageable<T>.AsPages
方法:
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# 程式碼中:
- 方法 SecretClient.GetPropertiesOfSecretsAsync 會叫用並傳
AsyncPageable<SecretProperties>
回物件。 - 叫用AsyncPageable<T>.AsPages並傳回
IAsyncEnumerable<Page<SecretProperties>>
。 - 使用
await foreach
以異步方式逐一遍歷每個頁面。 - 每個頁面都有一組Page<T>.Values,這表示一個
IReadOnlyList<T>
以同步的foreach
反覆迭代。 - 每個頁面也包含 Page<T>.ContinuationToken,可用來要求下一頁。
使用 System.Linq.Async
搭配 AsyncPageable
System.Linq.Async
套件提供一組 LINQ 方法,這些方法可以在 類型上運作。 由於 AsyncPageable<T>
實作 IAsyncEnumerable<T>
,因此您可以使用 System.Linq.Async
來查詢和轉換數據。
轉換成 List<T>
使用 ToListAsync
將 AsyncPageable<T>
轉換成 List<T>
。 如果未在單一頁面中傳回數據,這個方法可能會進行數個服務呼叫。
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
可以用來取得 N
的前 AsyncPageable
個元素。 使用 Take
會進行取得 N
專案所需的最少服務呼叫。
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
對應專案相等的功能。 這類方法的範例包括 Select
、 Where
、 OrderBy
和 GroupBy
。
注意客戶端評估
使用 System.Linq.Async
封裝時,請注意LINQ作業會在用戶端上執行。 下列查詢會提取 所有 項目,只是為了計算它們的數量:
// ⚠️ 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>
實現:
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
擴充方法,如下所示:
IDisposable UseTheToObservableMethod()
{
AsyncPageable<SecretProperties> allSecrets =
client.GetPropertiesOfSecretsAsync();
IObservable<SecretProperties> observable = allSecrets.ToObservable();
return observable.Subscribe(
new SecretPropertyObserver());
}
在上述 C# 程式碼中:
- 方法 SecretClient.GetPropertiesOfSecretsAsync 會叫用並傳
AsyncPageable<SecretProperties>
回物件。 - 在
ToObservable()
實體上呼叫AsyncPageable<SecretProperties>
方法,並返回IObservable<SecretProperties>
。 -
observable
被訂閱,並將觀察者實作傳入,然後把訂閱傳回給呼叫者。 - 訂閱是
IDisposable
。 處理完畢後,訂閱就會終止。
逐一查看可分頁
Pageable<T>
是的同步版本 AsyncPageable<T>
,可與一般 foreach
迴圈搭配使用。
void IterateWithPageable()
{
Pageable<SecretProperties> allSecrets = client.GetPropertiesOfSecrets();
foreach (SecretProperties secret in allSecrets)
{
Console.WriteLine($"IterateWithPageable: {secret.Name}");
}
}
這很重要
雖然此同步 API 可供使用,但請使用異步 API 替代專案,以取得較佳的體驗。