OData“列表中的 ID”查询

Posted

技术标签:

【中文标题】OData“列表中的 ID”查询【英文标题】:OData "where ID in list" query 【发布时间】:2011-12-06 09:51:26 【问题描述】:

我有一个 OData 服务,我正在尝试按 ID 列表进行过滤; SQL 等价物类似于:

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

我要过滤的属性类型为 Int32。我尝试了以下方法,这给了我一个错误“运算符'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”子句?

【问题讨论】:

gist.github.com/mausch/6893533 【参考方案1】:

使用OData 4.01,支持in 语句,如下所示:

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

【讨论】:

他们只用了 7 年。 :D 谢谢!【参考方案2】:

查看接受的答案,以下所有内容均适用于 OData v

试试这个

 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 Selectstring.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 中有 lambda 表达式 anyall,与数组文字 ["a", "b"] 配对,它们可能作为 in 工作,但我无法在 OData 使用 v4 端点提出工作示例.org

【讨论】:

这会引发错误:“将 Linq 表达式转换为 URI 时出错:不支持‘Select’方法。”不过,好主意。 这就是我所期望的。所以你唯一的选择是使用第二种方法,当你不知道你事先有多少个列表中的元素时,这会很容易 是的,带有 $filter 的循环是我最终做的。希望我永远不会超过 URL 长度限制! :-D 您可以设置限制并拆分您的 id 列表,一次查询 50 个 "...由于 OData 不支持 IN 语句...",这是我一直在寻找的关键【参考方案3】:

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

它并不优雅,您不会希望将它用于大量 id (> ~60) 列表,但它会解决问题。

【讨论】:

【参考方案4】:

如果我们需要更多 50 或 60 个 id,则扩展 MCattle 建议,然后建议在 2 个或更多并行调用中进行,并将它们添加到并发字典或类似的东西中,因为我们从服务器获取结果。虽然这增加了对服务器的调用次数,但由于我们正在慢慢转向云环境,我认为这应该不是一个大问题。

【讨论】:

以上是关于OData“列表中的 ID”查询的主要内容,如果未能解决你的问题,请参考以下文章

Odata中的子选择

Net Core:在洋葱架构中使用OData,将查询参数转换为Linq

在 excel 电源查询中使用带有参数的 OData 提要

扩展属性中的 Odata 过滤不起作用

武装你的WEBAPI-OData聚合查询

武装你的WEBAPI-OData便捷查询