2012-11-19 16 views
5

Vorrei recuperare le righe migliori n dalla tabella di Azure con un semplice TableQuery. Ma con il codice qui sotto, tutte le righe vengono recuperate indipendentemente dal mio limite con il Take.Perché il mio TakeLimit non è onorato da TableQuery?

Cosa sto sbagliando?

int entryLimit = 5; 

var table = GetFromHelperFunc(); 

TableQuery<MyEntity> query = new TableQuery<MyEntity>() 
    .Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "MyPK")) 
    .Take(entryLimit); 

List<FeedEntry> entryList = new List<FeedEntry>(); 
TableQuerySegment<FeedEntry> currentSegment = null; 

while (currentSegment == null || currentSegment.ContinuationToken != null) 
{ 
    currentSegment = table.ExecuteQuerySegmented(query, this.EntryResolver, currentSegment != null ? currentSegment.ContinuationToken : null); 
    entryList.AddRange(currentSegment.Results); 
} 


Trace.WriteLine(entryList.Count) // <-- Why does this exceed my limit? 
+1

La risposta accettata non è corretta - vedere la risposta di Fabrzio. – Ryan

risposta

12

Il metodo Take sull'SDK di archiviazione non funziona come in LINQ. Immaginate di fare qualcosa di simile:

TableQuery<TableEntity> query = new TableQuery<TableEntity>() 
       .Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "temp")) 
       .Take(5); 
var result = table.ExecuteQuery(query); 

Quando si avvia l'iterazione di result avrete inizialmente ottiene solo 5 elementi. Ma al di sotto, se continui a ripetere il numero result, l'SDK continuerà a interrogare la tabella (e procede alla successiva 'pagina' di 5 elementi).

Se ho 5000 articoli nel mio tavolo, questo codice di uscita tutti i 5000 articoli (e sotto l'SDK farà 1000 richieste a prendere 5 articoli per richiesta):

TableQuery<TableEntity> query = new TableQuery<TableEntity>() 
       .Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "temp")) 
       .Take(5); 
var result = table.ExecuteQuery(query); 
foreach (var item in result) 
{ 
    Trace.WriteLine(item.RowKey); 
} 

Il seguente codice preleverà esattamente 5 articoli in 1 richiesta e si fermano qui:

TableQuery<TableEntity> query = new TableQuery<TableEntity>() 
       .Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "temp")) 
       .Take(5); 
var result = table.ExecuteQuery(query); 
int index = 0; 
foreach (var item in result) 
{ 
    Console.WriteLine(item.RowKey); 
    index++; 
    if (index == 5) 
     break; 
} 

in realtà, il metodo diTake() imposta le dimensioni della pagina o il "prendere count" (TakeCount proprietà su TableQuery). Ma spetta a te interrompere l'iterazione in tempo se vuoi solo 5 record.

Nel tuo esempio, è necessario modificare il ciclo while per fermare quando si raggiunge la TakeCount (che si imposta chiamando Prendere):

while (entryList.Count < query.TakeCount && (currentSegment == null || currentSegment.ContinuationToken != null)) 
{ 
    currentSegment = table.ExecuteQuerySegmented(query, currentSegment != null ? currentSegment.ContinuationToken : null); 
    entryList.AddRange(currentSegment.Results); 
} 
+0

Grazie mille per un'ottima spiegazione! –

+4

Sandrino, sei sicuro della risposta? Nel mio test, Take funziona correttamente. Forse stai facendo riferimento a una versione vecchia e bug di StorageClient https://github.com/WindowsAzure/azure-sdk-for-net/issues/144 –

+0

Nuget 9.1.0 ha ancora il problema e ha dovuto seguire la raccomandazione qui. –

Problemi correlati