Domanda

Ho bisogno di selezionare più file all'interno di una singola partizione delle tabelle Azure per l'aggiornamento più tardi. Dal momento che tutti hanno lo stesso PartitionKey, come faccio a strutturare la mia domanda per selezionare più RowKeys?

Mi interessa ciò che la prima (sul filo) query dovrebbe essere simile, e, se possibile, la query LINQ pure.

Ho tentato per conto mio e ha iniziato con questa domanda:

 var results = from c in _ServiceContext.ForumThreadTable
                          where(
                          (
                          (c.RowKey == rk)    ||
                          (c.RowKey == "n1q") ||
                          (c.RowKey == "gm1w") ||
                          (c.RowKey == "fm1e") ||
                          (c.RowKey == "zbm1r") ||
                          (c.RowKey == "km1te1") ||
                          (c.RowKey == "jm1ye1") ||
                          (c.RowKey == "hm1u") ||
                          (c.RowKey == "gm1i") ||
                          (c.RowKey == "fm1te1") ||
                          (c.RowKey == "d4m1ye1") ||
                          (c.RowKey == "bm1u") ||
                          (c.RowKey == "bm1i") ||
                          (c.RowKey == "bm1o") ||
                          (c.RowKey == "bp1p") 
                          ) &&

                          c.PartitionKey == pk )
                          select c;

La mia domanda si presentava così (da Fiddler)

GET http://127.0.0.1:10002/devstoreaccount1/ForumThreadTable()?$filter=(((((((((((((((RowKey%20eq%20'0634205427898279774')%20or%20(RowKey%20eq%20'n1q'))%20or%20(RowKey%20eq%20'gm1w'))%20or%20(RowKey%20eq%20'fm1e'))%20or%20(RowKey%20eq%20'zbm1r'))%20or%20(RowKey%20eq%20'km1te1'))%20or%20(RowKey%20eq%20'jm1ye1'))%20or%20(RowKey%20eq%20'hm1u'))%20or%20(RowKey%20eq%20'gm1i'))%20or%20(RowKey%20eq%20'fm1te1'))%20or%20(RowKey%20eq%20'd4m1ye1'))%20or%20(RowKey%20eq%20'bm1u'))%20or%20(RowKey%20eq%20'bm1i'))%20or%20(RowKey%20eq%20'bm1o'))%20or%20(RowKey%20eq%20'bp1p'))%20and%20(PartitionKey%20eq%20'GUIDeec4550c-a3fd-472b-9b7d-c79fae664415') HTTP/1.1
User-Agent: Microsoft ADO.NET Data Services
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 2.0;NetFx
x-ms-version: 2009-09-19
x-ms-date: Mon, 20 Sep 2010 02:49:48 GMT
Authorization: SharedKeyLite devstoreaccount1:MINFtQhWqbnYhn1spDGTGvPmNmW24YNzOeqBBtOletU=
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8
Host: 127.0.0.1:10002

e qui è il mio errore:

"<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>
 <error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">
 <code>InvalidInput</code>
 <message xml:lang=\"en-US\">One of the request inputs is not valid.</message>
 </error>"

penso che possa avere a che fare più con la quantità di condizioni RowKey ho, piuttosto che la sintassi ... ma io sono aperto a provare qualsiasi cosa.

Grazie!

È stato utile?

Soluzione

Questo è qualcosa di simile a quello che abbiamo fatto in Lokad.Cloud . Se non ricordo male è possibile selezionare fino a 100 righe in questo modo senza problemi. È possibile controllare il codice sorgente per i dettagli e il riutilizzo o l'intero progetto open source o solo le parti che ti piace.

Ecco come gli sguardi generazione sintassi come:

public IEnumerable<CloudEntity<T>> Get<T>(string tableName, string partitionKey, IEnumerable<string> rowKeys)
{
  Enforce.That(() => tableName);
  Enforce.That(() => partitionKey);
  Enforce.That(!partitionKey.Contains("'"), "Incorrect char in partitionKey.");

  var context = _tableStorage.GetDataServiceContext();

  foreach (var slice in rowKeys.Slice(MaxEntityTransactionCount))
  {
    // work-around the limitation of ADO.NET that does not provide a native way
    // of query a set of specified entities directly.
    var builder = new StringBuilder();
    builder.Append(string.Format("(PartitionKey eq '{0}') and (", HttpUtility.UrlEncode(partitionKey)));
    for (int i = 0; i < slice.Length; i++)
    {
      // in order to avoid SQL-injection-like problems 
      Enforce.That(!slice[i].Contains("'"), "Incorrect char in rowKey.");

      builder.Append(string.Format("(RowKey eq '{0}')", HttpUtility.UrlEncode(slice[i])));
      if (i < slice.Length - 1)
      {
        builder.Append(" or ");
      }
    }
    builder.Append(")");

    foreach(var entity in GetInternal<T>(context, tableName, builder.ToString()))
    {
      yield return entity;
    }
  }
}

Tuttavia, tieni presente che questa operazione non sarà ottimizzata la memorizzazione delle tabelle, con conseguente prestazioni non ottimali (memorizzazione tabella non utilizza gli indici per questa operazione). Questo è un bug che è stato segnalato a Microsoft e dovrebbe essere fissato un po 'di tempo al più presto.

Altri suggerimenti

Hai qualche aggiornamento sui progressi compiuti con questo bug fix. È di stoccaggio Azure Table ora eseguire questo tipo di query (rowkey multiple con OR operazione su un'unica partizione) utilizzando gli indici?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top