OData 4 客户端和带浮点数的过滤器

OData 4 Clients and filters with floats

我们正在使用 OData 4 Client Generator 创建一些代理 类 并查询 OData4 服务。一切似乎都工作正常,除了我们想要按浮点数或双精度属性过滤的查询。

因此对于使用整数过滤器进行的给定查询:

var ctx = new ODataClient(new Uri("http://..."));
var intFilter = 3;
var results = ctx.Entities.Where(e => e.IntProperty == intFilter).ToList();

对服务的结果查询是:

Entities?$filter=IntProperty eq 3

我们得到了过滤后的结果,正如预期的那样。

但是如果我们尝试使用双精度值进行过滤,例如:

var ctx = new ODataClient(new Uri("http://..."));
var doubleFilter = 0.35d;
var results = ctx.Entities.Where(e => e.DoubleProperty == doubleFilter).ToList();

查询结果为:

Entities?$filter=DoubleProperty eq 0.35

实际上应该是:

Entities?$filter=DoubleProperty eq 0.35d

最后的微小差异导致服务开始抛出异常:

The query specified in the URI is not valid. 
Numeric string '0.35' is not a valid Int32/Int64/Double/Decimal.

有什么方法可以配置这些代理客户端以正确进行转换吗?或者我们是否坚持使用 AddQueryOption 方法并且必须构建我们的过滤器 "manually" 而不是使用 LINQ?

不要像

那样发送
var doubleFilter = 0.35d;

改为像

一样发送
decimal doubleFilter = 0.35;

这将解决您的问题

Entities?$filter=DoubleProperty eq 0.35 实际上是一个预期的表达式,如果你看一下 OData protocal 5.1.1.6.1 Primitive Literals

原始文字可以作为键 属性 值出现在资源路径中,也可以出现在查询部分,例如,作为 $filter 表达式中的操作数。它们根据 [OData-ABNF].

中的 primitiveLiteral 规则表示

OData-ABNF定义PrimitiveLiteral如下:

;在网址中

primitiveLiteral = nullValue                  ; plain values up to int64Value
             / ...
             / doubleValue 
             / singleValue 
             / ...

decimalValue = [SIGN] 1*DIGIT ["." 1*DIGIT]

doubleValue = decimalValue [ "e" [SIGN] 1*DIGIT ] / nanInfinity ; IEEE 754 binary64 floating-point number (15-17 decimal digits)
singleValue = doubleValue 

所以我觉得你们的服务支持提升0.35翻倍比较好

要解决此问题,实际上您可以使用 AddQueryOption,如下所示。

ctx.Entities.AddQueryOption("$filter", "DoubleProperty eq 0.35d").ToList();