2012-10-18 14 views
7

私のアプリケーションでは、partitionkeyが定数ですが行の文字列がレキシカル範囲内にあるすべてのエンティティを取得するクエリを作成するアプリケーションでよく発生します)いくつかのプレフィックスで:などSTARTSWITHなどの文字列関数は、クエリのこの種ではサポートされていないため一般的に使用されている条件がメソッドにラップされたAzureテーブルの格納域のクエリ

//query to get all entities in partition "KnownPartition" where RowKey starts with "Prefix_" 
CloudTableQuery<MyEntity> query = 
    (from e in tableServiceContext.CreateQuery<MyEntity>(tableName) 
    where e.PartitionKey == "KnownPartition" 
      && e.RowKey.CompareTo("Prefix_") > 0 
      && e.RowKey.CompareTo("Prefix`") <= 0 // ` is '_' + 1 
    select e).AsTableServiceQuery(); 

私はのCompareToを使用する必要があります。これはうまくいきますが、その状態は読みにくく、繰り返したくさんあります。だからではなく、この読みにくい条件でクエリをたくさん書いて、私はむしろそれを「インライン化」機能をしたいのですが:

public static Boolean HasPrefix(this String rowKey, String prefix) 
{ 
    return rowKey.CompareTo(prefix + '_') > 0 && rowKey.CompareTo(prefix + '`') <= 0; 
} 

CloudTableQuery<MyEntity> query = 
    (from e in tableServiceContext.CreateQuery<MyEntity>(tableName) 
    where e.PartitionKey == "KnownPartition" && e.RowKey.HasPrefix("Prefix") 
    select e).AsTableServiceQuery(); 

しかし、私はこれを実行すると、私はから例外を取得私の機能についてのAzureはサポートされていません。サポートされるようにこれを書く方法はありますか?結局のところ、私は機能しているクエリとまったく同じ条件を使用しています...

答えて

10

条件を関数に分割すると、関数は式ツリーを返す必要はなくなります。ブール値LINQクエリ構文は、これをサポートするかどうかは分かりませんが、次のようにメソッドの構文でそれを行うことができます:ここで

public static Expression<Func<MyEntity, bool>> HasPrefix(String prefix) 
{ 
    return e => e.RowKey.CompareTo(prefix + '_') > 0 && e.RowKey.CompareTo(prefix + '`') <= 0; 
} 

CloudTableQuery<MyEntity> query = 
    (from e in tableServiceContext.CreateQuery<MyEntity>(tableName) 
    where e.PartitionKey == "KnownPartition" 
    select e) 
    .Where(HasPrefix("Prefix")) 
    .AsTableServiceQuery(); 
+0

非常にクールです。ありがとうございました。私は、すべての式をlinqクエリ構文ではなくむしろメソッドチェーンとして書くことができると思います。 –

+0

ああ、ところで、私はこれがフルスキャンにならないことを願っています...実際には、azureから実際に転送されたエンティティはプレフィックス条件がチェックされています。 –

+1

結果AzureストレージリクエストURIは次のとおりです。https://foo.table.core.windows.net/tablename()?$filter=((PartitionKey eq 'KnownPartition')および(RowKey gt 'Prefix_'))および(RowKey le 'Prefix%60')。したがって、すべての条件を満たす行のみが返されます。さらに、問合せではパーティション・キーと行キーの範囲が指定されているため、バックエンドでもフル・テーブル・スキャンは不要です。 – Kevin

17

はケビンの答えを一般化したものです。同じことをしますが、デビッドが元の質問で尋ねた特定のケースだけではなく、任意のプレフィックス文字列に対して機能します。

public static Expression<Func<MyEntity, bool>> HasPrefix(String prefix) 
{ 
    char lastChar = prefix[prefix.Length - 1]; 
    char nextLastChar = (char)((int)lastChar + 1); 
    string nextPrefix = prefix.Substring(0, prefix.Length - 1) + nextLastChar; 

    return e => e.RowKey.CompareTo(prefix) >= 0 && e.RowKey.CompareTo(nextPrefix) < 0; 
} 
+0

一般的な答えを提供してくれてありがとう! MSはちょうどLinqの質問プロセッサーにこのビットを含んでいるはずです! –

関連する問題