我们使用OData4 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方法困住了,不得不"手动"构建我们的过滤器,而不是用LINQ?
Entities?$filter=DoubleProperty eq 0.35
实际上是一个期望的表达式,如果你看一下OData协议5.1.1.6.1原始文字
基本字面值可以作为关键属性值出现在资源路径中,也可以作为查询部分的操作数出现在$filter表达式中。它们是根据[OData-ABNF]中的primitivelital规则表示的。
OData-ABNF对PrimitiveLiteral
的定义如下:
;在url
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();
不要这样发送
var doubleFilter = 0.35d;
而不是像
那样发送decimal doubleFilter = 0.35;
这将解决你的问题