Eventi
Paginazione con Azure SDK per .NET
Questo articolo illustra come usare la funzionalità di paginazione di Azure SDK per .NET in modo efficiente e produttivo con set di dati di grandi dimensioni. La funzionalità di paginazione è l'atto di dividere set di dati di grandi dimensioni in pagine, semplificando l'iterazione da parte del consumer tramite quantità ridotte di dati. A partire da C# 8, è possibile creare e utilizzare i flussi in modo asincrono tramite flussi (asinc) asincroni. I flussi asincroni si basano sull'interfaccia IAsyncEnumerable<T>. Azure SDK per .NET espone un'implementazione di IAsyncEnumerable<T>
con la relativa classe AsyncPageable<T>
.
Tutti gli esempi in questo articolo si basano sui pacchetti NuGet seguenti:
- Azure.Security.KeyVault.Secrets
- Microsoft.Extensions.Azure
- Microsoft.Extensions.Hosting
- System.Linq.Async
Per la directory più recente dei pacchetti di Azure SDK per .NET, vedere Versioni più recenti di Azure SDK.
I client di cui è stata creata un'istanza da Azure SDK per .NET possono restituire i tipi sottoponibili a paginazione seguenti.
Tipo | Descrizione |
---|---|
Pageable<T> |
Una raccolta di valori recuperati nelle pagine |
AsyncPageable<T> |
Raccolta di valori recuperati in modo asincrono nelle pagine |
La maggior parte degli esempi in questo articolo è asincrona, con le varianti del tipo AsyncPageable<T>
in uso. L'uso della programmazione asincrona per le operazioni associate a I/O è ideale. Un caso d'uso perfetto usa le API asincrone di Azure SDK per .NET perché queste operazioni rappresentano chiamate di rete HTTP/S.
Per eseguire l'iterazione di un oggetto AsyncPageable<T>
usando la sintassi await foreach
, considerare l'esempio seguente:
async Task IterateSecretsWithAwaitForeachAsync()
{
AsyncPageable<SecretProperties> allSecrets = client.GetPropertiesOfSecretsAsync();
await foreach (SecretProperties secret in allSecrets)
{
Console.WriteLine($"IterateSecretsWithAwaitForeachAsync: {secret.Name}");
}
}
Nel codice C# precedente:
- Il metodo SecretClient.GetPropertiesOfSecretsAsync viene richiamato e restituisce un oggetto
AsyncPageable<SecretProperties>
. - In un ciclo
await foreach
, ogniSecretProperties
viene sospeso in modo asincrono. - Ogni volta in cui un oggetto
secret
viene materializzato, il relativoName
viene scritto nella console.
Per eseguire l'iterazione di un oggetto AsyncPageable<T>
quando la sintassi await foreach
non è disponibile, usare un ciclo 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();
}
}
Nel codice C# precedente:
- Il metodo SecretClient.GetPropertiesOfSecretsAsync viene richiamato e restituisce un oggetto
AsyncPageable<SecretProperties>
. - Il metodo AsyncPageable<T>.GetAsyncEnumerator viene richiamato, restituendo un oggetto
IAsyncEnumerator<SecretProperties>
. - Il metodo MoveNextAsync() viene richiamato ripetutamente fino a quando non sono presenti elementi da restituire.
Se si vuole controllare la ricezione di pagine di valori dal servizio, usare il metodo 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);
}
}
Nel codice C# precedente:
- Il metodo SecretClient.GetPropertiesOfSecretsAsync viene richiamato e restituisce un oggetto
AsyncPageable<SecretProperties>
. - Il metodo AsyncPageable<T>.AsPages viene richiamato e restituisce un elemento
IAsyncEnumerable<Page<SecretProperties>>
. - Viene eseguita l'iterazione di ogni pagina in modo asincrono usando
await foreach
. - Ogni pagina ha un set di Page<T>.Values, che rappresenta un oggetto
IReadOnlyList<T>
di cui è stata eseguita l'iterazione con un oggetto sincronoforeach
. - Ogni pagina contiene anche un oggetto Page<T>.ContinuationToken, che può essere usato per richiedere la pagina successiva.
Il pacchetto System.Linq.Async
fornisce un set di metodi LINQ che operano sul tipo IAsyncEnumerable<T>. Dato che AsyncPageable<T>
implementa IAsyncEnumerable<T>
, è possibile usare System.Linq.Async
per eseguire query e trasformare i dati.
Usare ToListAsync
per convertire un oggetto AsyncPageable<T>
in un elemento List<T>
. Questo metodo potrebbe effettuare diverse chiamate al servizio se i dati non vengono restituiti in una singola pagina.
async Task ToListAsync()
{
AsyncPageable<SecretProperties> allSecrets =
client.GetPropertiesOfSecretsAsync();
List<SecretProperties> secretList = await allSecrets.ToListAsync();
secretList.ForEach(secret =>
Console.WriteLine($"ToListAsync: {secret.Name}"));
}
Nel codice C# precedente:
- Il metodo SecretClient.GetPropertiesOfSecretsAsync viene richiamato e restituisce un oggetto
AsyncPageable<SecretProperties>
. - Si attende che il metodo
ToListAsync
materializzi una nuova istanzaList<SecretProperties>
.
Take
può essere usato per ottenere solo i primi N
elementi dell'oggetto AsyncPageable
. L'uso di Take
consentirà di eseguire il minor numero di chiamate di servizio necessarie per ottenere N
elementi.
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
offre altri metodi che forniscono funzionalità equivalenti alle Enumerable
controparti sincrone. Esempi di tali metodi sono Select
, Where
, OrderBy
e GroupBy
.
Quando si usa il pacchetto System.Linq.Async
, tenere presente che le operazioni LINQ vengono eseguite nel client. La query seguente recupera tutti gli elementi solo per conteggiarli:
// ⚠️ DON'T DO THIS! 😲
int expensiveSecretCount =
await client.GetPropertiesOfSecretsAsync()
.CountAsync();
Avviso
Lo stesso avviso si applica agli operatori come Where
. Preferire sempre filtri lato server, aggregazione o proiezioni di dati, se disponibili.
Il pacchetto System.Linq.Async
viene usato principalmente per fornire funzionalità del criterio osservatore sulle sequenze IAsyncEnumerable<T>
. I flussi asincroni sono basati sul pull. A mano a mano che si esegue l'iterazione degli elementi, viene eseguito il pull dell'elemento disponibile successivo. Questo approccio è in sovrapposizione con il modello osservatore, che è basato su push. A mano a mano che gli elementi diventano disponibili, viene eseguito il push ai sottoscrittori che fungono da osservatori. Il pacchetto System.Linq.Async
fornisce il metodo di estensione ToObservable
, che consente di convertire un oggetto IAsyncEnumerable<T>
in un elemento IObservable<T>
.
Immaginare un'implementazione di 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}");
}
È possibile utilizzare il metodo ToObservable
di estensione come indicato di seguito:
IDisposable UseTheToObservableMethod()
{
AsyncPageable<SecretProperties> allSecrets =
client.GetPropertiesOfSecretsAsync();
IObservable<SecretProperties> observable = allSecrets.ToObservable();
return observable.Subscribe(
new SecretPropertyObserver());
}
Nel codice C# precedente:
- Il metodo SecretClient.GetPropertiesOfSecretsAsync viene richiamato e restituisce un oggetto
AsyncPageable<SecretProperties>
. - Il metodo
ToObservable()
viene chiamato nell'istanzaAsyncPageable<SecretProperties>
, restituendo un oggettoIObservable<SecretProperties>
. - Viene eseguita la sottoscrizione a
observable
, passando l'implementazione dell'osservatore, restituendo la sottoscrizione al chiamante. - La sottoscrizione è un elemento
IDisposable
. Quando viene eliminato, la sottoscrizione termina.
Pageable<T>
è una versione sincrona di AsyncPageable<T>
, che può essere usata con un ciclo foreach
normale.
void IterateWithPageable()
{
Pageable<SecretProperties> allSecrets = client.GetPropertiesOfSecrets();
foreach (SecretProperties secret in allSecrets)
{
Console.WriteLine($"IterateWithPageable: {secret.Name}");
}
}
Importante
Anche se questa API sincrona è disponibile, usare le API asincrone alternative per un'esperienza migliore.
Feedback su .NET
.NET è un progetto di open source. Selezionare un collegamento per fornire feedback: