Подтвердить что ты не робот

Запрос OData "where ID in list"

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

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

Свойство, которое я пытаюсь фильтровать, набирается как Int32. Я пробовал следующее, что дает мне ошибку "Operator" add 'несовместим с типами операндов "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?

4b9b3361

Ответ 1

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

 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 ...");

который можно построить с помощью цикла или 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);

UPDATE: существует операция фильтрации field=["a","b"], но это означает что-то другое.

UPDATE2: В OData V4 есть лямбда-выражения any и all, в паре с литералом массива ["a", "b"] они могут работать как IN, но мне не удалось найти рабочий синтаксис на примере конечной точки v4 в OData. Org

Ответ 2

Развернувшись на 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), но это будет трюк.

Ответ 3

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