OData запрос "где ID в списке" - PullRequest
48 голосов
/ 12 октября 2011

У меня есть служба OData, где я пытаюсь фильтровать по списку идентификаторов;SQL-эквивалент будет выглядеть примерно так:

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

Свойство, по которому я пытаюсь фильтровать, имеет тип Int32.Я пробовал следующее, что дает мне ошибку «Оператор« добавить »несовместим с типами операндов« Edm.String »и« Edm.Int32 »»:

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

Ответы [ 4 ]

35 голосов
/ 12 октября 2011

См. Принятый ответ, все ниже для OData v <4.01 </strong>

попробуйте это

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

подробное описание msdn для запросов к DataServices.

другой подход будет

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

и поскольку OData не поддерживает операторы IN, вы получите условие фильтра, подобное этому

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

, который вы можете построить используя loop или 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, но я не смог придумать рабочий пример с использованием конечной точки v4 в OData .org

20 голосов
/ 09 августа 2018

С OData 4.01 , оператор in поддерживается следующим образом:

http://host/service/Products?$filter=Name in ('Milk', 'Cheese')
13 голосов
/ 12 апреля 2013

Расширяя ответ vittore (из которых вторая часть является правильным ответом), я написал нечто подобное для демонстрационного проекта:

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();

Это не элегантно, и вы не захотите использовать это для большого списка идентификаторов (> ~ 60), но это поможет.

0 голосов
/ 19 сентября 2014

Расширение на предложение MCattle, если нам нужно больше 50 или 60 идентификаторов, тогда его целесообразно сделать в 2 или более параллельных вызовах и добавить их в параллельный словарь или что-то подобное, когда мы получаем результаты с сервера. Хотя это увеличивает количество обращений к серверу, но, поскольку мы постепенно переходим в облачную среду, на мой взгляд, это не должно быть большой проблемой.

...