web-dev-qa-db-ja.com

OData「リスト内のID」クエリ

IDのリストでフィルタリングしようとしているODataサービスがあります。同等のSQLは次のようになります。

SELECT * FROM MyTable WHERE TableId IN (100, 200, 300, 400)

フィルタリングしようとしているプロパティは、Int32として入力されています。次のことを試してみましたが、「オペランド 'Edm.String'および 'Edm.Int32'と互換性のない演算子 'add'」というエラーが表示されます。

string ids = ",100,200,300,400,";
from m in provider.Media where ids.Contains("," + t.media_id + ",")

と同様

string ids = ",100,200,300,400,";
from m in provider.Media where ids.Contains("," + t.media_id.ToString() + ",")

そして

string ids = ",100,200,300,400,";
from m in provider.Media where ids.Contains("," + Convert.ToString(t.media_id) + ",")

そして

string ids = ",100,200,300,400,";
from m in provider.Media where ids.Contains(string.Concat(",", t.media_id, ","))

ご覧のとおり、現在、LINQを使用してサービスを照会しています。

私がしようとしていることを行う方法はありますか、テキストフィルタを構築してAddQueryOptionを使用し、リストを反復処理し、手動で「またはmedia_id eq 100」句を追加しますか?

50
technophile

OData 4.01 の場合、inステートメントは次のようにサポートされます。

http://Host/service/Products?$filter=Name in ('Milk', 'Cheese')
25
martinoss

受け入れられた答えを参照してください、以下はすべてOData v <4.01のものです

これを試して

 var ids = new [] { 100, 200, 300 } ;
 var res = from m in provider.Media 
           from id in ids 
           where m.media_id == id 
           select m;

dataServicesのクエリに関する msdn に関する包括的な説明があります。

別のアプローチは

var results = provider.Media
   .AddQueryOption("$filter", "media_id eq 100");

oDataはINステートメントをサポートしていないので、このようなフィルター条件を思いつくでしょう

.AddQueryOption("$filter", "(media_id eq 100) or (media_id eq 200 ) or ...");

ループまたはlinq Selectおよびstring.Joinを使用して構築できます。

var ids = new [] { 100, 200, 300 };
var filter = string.Join(" or ", ids.Select(i=> $"(media_id eq {i})"));
var results = provider.Media.AddQueryOption("$filter", filter);

更新:フィルター操作field=["a","b"]がありますが、別の意味があります。

UPDATE2:OData V4には、ラムダ式anyおよびallがあり、配列リテラル["a", "b"]とペアになっていますが、inとして機能する可能性がありますOData.orgでv4エンドポイントを使用した作業例

35
vittore

vittore の答え(2番目の部分は正しい答えです)を展開して、デモプロジェクト用に次のようなものを書きました。

var filterParams = ids.Select(id => string.Format("(media_id eq {0})", id));
var filter = string.Join(" or ", filterParams);
var results = provider.Media.AddQueryOption("$filter", filter).Execute().ToList();

これはエレガントではなく、これをidの大きなリスト(>〜60)に使用することは望ましくありませんが、トリックを実行します。

13
MCattle

50または60以上のIDが必要な場合はMCattleの提案を拡張し、2つ以上の並列呼び出しで実行し、同時辞書またはサーバーから結果を取得するときに類似したものに追加することをお勧めします。これによりサーバーへの呼び出し回数が増えますが、クラウド環境にゆっくりと移行しているため、私の意見では大きな問題ではないはずです。

0
Navap