OrおよびContainsを実装するAzure Table StorageのLINQ Extensions

みなさんこんにちは! シリーズ「AtContent.comサービスの内部デバイスとアーキテクチャ」の第5回の記事をご紹介します。 その中で、Azure Table Storageをより機能的かつ便利に使用する方法について説明します。



LINQ



Windows Azureプラットフォームは、アイデアを実装するための非常に強力なツールセットを提供します。 そしてその中でも、Azure Table Storage-無制限の量の非リレーショナルデータベースです。 このストレージの大きな利点は、非常に複雑なクエリを実行できることです。 しかし、これ以外にもいくつかの不便があります。 そのため、たとえば、LINQを使用して、追加の変更なしにロジックOrまたはContainsを含むクエリを実行することはできません。



これに直面しなければならなかったとき、私たちは問題を研究し、REST APIの助けを借りてOrを持つリクエストを作成できることがわかりました。 そして、本当にそのようなリクエストが必要でした。 このために、LINQからREST APIにすべてのコードを書き換えないでください。 もう少し掘り下げて、解決策を見つけました!



したがって、Azure Table Storage-LINQ-を使用する便利な方法を維持し、Containsクエリを作成する機能を補完するには、クエリをREST APIに変換するときにLINQの深部で発生するメカニズムを解析する必要がありました。 問題自体は、WhereでのみLINQクエリを動的に変更できたことです。 この場合、式はAnd修飾子を使用してリクエストに追加されます。 したがって、And演算子で接続された可変数のパラメーターを使用してクエリを作成することは難しくありません。 Orに対して同じことを行う必要がある場合は、ラムダ式を使用して支援する必要があります。



もちろん、単に複数の要求を作成し、それらを1つに結合することもできますが、そのような無駄は、顧客または加入者のソリューションの最終コストに悪影響を及ぼします。 100分の1セントの1つのリクエストのコストでさえ、1つのリクエストと、たとえば10の違いは明らかです。 したがって、決定に進みます。



最初の試行は失敗しました。 検索エンジンはこの問題を解決できなかったため、実験を通して行動する必要がありました。 IQuerable.Where()では、Expression <Func <T、bool >>に置き換えることができます。 悲しみを半分にしてそのような表現をし、それをテストした後、私は失望しました。 Invoke()の後の結果の式にはクラス名が含まれており、Azure Table Storageへのそのようなクエリは確かに例外を返しました。



しかし、それは私を止めませんでした。 LINQの代わりにREST APIを使用する見込みがあるため、目が覚めました。 わずか数日間のMSDNの集中的な読書とエレガントなソリューションが生まれました。これは非常に簡単に適用できます。



public static class LinqExtension { public static Expression<Func<T, bool>> Contains<T>(string ObjectStringName, string FieldStringNameToCompare, IList<String> ListOfValues) { Expression ExprBody = null; ParameterExpression ParameterObject = Expression.Parameter(typeof(T), ObjectStringName); var PropertyFieldToCompare = Expression.Property(ParameterObject, FieldStringNameToCompare); foreach (var ValueToCompare in ListOfValues) { ConstantExpression ValueConst = Expression.Constant(ValueToCompare, typeof(string)); BinaryExpression EqualTermExpression = Expression.Equal(PropertyFieldToCompare, ValueConst); if (ExprBody == null) { ExprBody = EqualTermExpression; } else { ExprBody = Expression.Or(ExprBody, EqualTermExpression); } } if (ExprBody == null) { ExprBody = Expression.IsTrue(Expression.Constant(false)); } var FinalExpression = Expression.Lambda<Func<T, bool>>(ExprBody, new ParameterExpression[] { ParameterObject }); return FinalExpression; } public static IQueryable<T> Contains<T>(this IQueryable<T> obj, string ObjectStringName, string FieldStringNameToCompare, IList<String> ListOfValues) { var Expression = Contains<T>(ObjectStringName, FieldStringNameToCompare, ListOfValues); if (Expression != null) return obj.Where<T>(Expression); return obj; } }
      
      





これにより、Contains操作をリクエストに適用できます。 したがって、SQLのIN操作の類似物が取得されます。 これにより、プロジェクトでのAzure Table Storageの適用範囲が大幅に拡大しました。



この実装では、ラムダ式は段階的に構築され、数日間眠りにつかなかった行は次のようになっていることに注意してください。

 ConstantExpression ValueConst = Expression.Constant(ValueToCompare, typeof(string));
      
      





invoke()が実行されたときに、オブジェクトの値ではなく定数を置き換える必要があることを示すのは彼女です。

ここで示した実装は文字列値でのみ機能しますが、これらのメソッドを任意の型で使用するために自分で拡張することを妨げるものは何もありません。



この記事に記載されているソリューションは、CPlase Open Sourceライブラリの一部であり、公開準備中です。



シリーズを読む:



私たちのサービスを試してみてください

満足



All Articles