2010-09-20 6 views
1

Je dois sélectionner plusieurs lignes dans une seule partition de Azure Tables pour une mise à jour ultérieure. Comme ils ont tous la même PartitionKey, comment structurer ma requête pour sélectionner plusieurs RowKeys?Comment sélectionner 50 à 100 lignes à partir de la table Azure à l'aide de StorageClient?

Je suis intéressé par ce à quoi devrait ressembler la requête brute (sur le réseau) et, si possible, la requête Linq.

J'ai essayé sur mon propre et a commencé avec cette requête:

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; 

Ma requête ressemblait à ceci (de 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 

et voici mon erreur:

"<?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>" 

Je pense qu'il peut avoir à faire plus avec la quantité de conditions RowKey que j'ai, plutôt que la syntaxe ... mais je suis ouvert pour essayer n'importe quoi.

Merci!

Répondre

2

C'est quelque chose de similaire à ce que nous avons fait dans Lokad.Cloud. Si je me souviens, vous pouvez sélectionner jusqu'à 100 lignes de cette manière sans problèmes. Vous pouvez vérifier le source code for the details et réutiliser le projet open source entier ou seulement les parties que vous aimez.

Voilà comment la génération de syntaxe ressemble à:

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; 
    } 
    } 
} 

Cependant, s'il vous plaît garder à l'esprit que cette opération ne sera pas optimisé par le stockage de la table, résultant en une performance sous-optimale (stockage de table n'utilise des index pour cette opération). C'est un bug qui a été signalé à Microsoft et devrait être corrigé dans un avenir proche.

1

Avez-vous une mise à jour sur la progression de cette correction de bogue. Le stockage Azure Table effectue-t-il désormais ce type de requête (plusieurs rowkey avec une opération OR sur une seule partition) à l'aide d'index?

Questions connexes