事件
使用 Azure SDK for .NET. 進行分頁
在本文中,您將了解如何使用 Azure SDK for .NET 分頁功能,以提升使用大型資料集的效率和生產力。 分頁是將大型資料集分割成頁面的動作,讓取用者更容易逐一查看較小的資料量。 從 C# 8 開始,您可以使用非同步 (async) 串流,以非同步方式建立和使用串流。 非同步串流是以 IAsyncEnumerable<T> 介面為基礎。 Azure SDK for .NET 會公開 IAsyncEnumerable<T>
的實作以及其 AsyncPageable<T>
類別。
本文中的所有範例都依賴以下 NuGet 套件:
- Azure.Security.KeyVault.Secrets
- Microsoft.Extensions.Azure
- Microsoft.Extensions.Hosting
- System.Linq.Async
如需 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<T>
,請考慮以下範例:
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
也會寫入主控台。
如要在 await foreach
語法不可用的情況下逐一查看 AsyncPageable<T>
,請使用 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<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,其代表系統以非同步
foreach
逐一查看的IReadOnlyList<T>
。 - 每個頁面也都包含 Page<T>.ContinuationToken,可用來要求下一個頁面。
System.Linq.Async
套件提供一組 LINQ 方法,能在 IAsyncEnumerable<T> 類型上運作。 因為 AsyncPageable<T>
會實作 IAsyncEnumerable<T>
,所以您可以使用 System.Linq.Async
來查詢和轉換資料。
使用 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>
執行個體。
Take
只能用來取得 AsyncPageable
的前 N
個元素。 使用 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>
物件。 - 系統會在
AsyncPageable<SecretProperties>
執行個體上呼叫ToObservable()
方法,傳回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 替代專案,以取得更好的體驗。