我正在使用来自https://github.com/OData/ODataSamples/tree/master/Scenarios/TripPin/src/webapi的TripPin OData演示,使用由以下VS扩展引入的OData模板生成的OData C#客户端代码:
C#代码很简单:
var dc = new DefaultContainer(new Uri("http://canws212:23890/"));
dc.People.AddQueryOption("$expand", "Trips").Where(p => p.Trips.Any()).First();
这将返回Person
属性中具有任何Trip
子实体的第一个Trips
实体。
但现在我想让第一个Person
实体拥有多个Trip
孩子:
dc.People.AddQueryOption("$expand", "Trips").Where(p => p.Trips.Count() > 1).First();
这不起作用。 fiddler捕获的请求/响应是:
请求
GET http://canws212:23890/People?$filter=Trips/$count%20gt%201&$top=1&$expand=Trips HTTP/1.1
OData-Version: 4.0
OData-MaxVersion: 4.0
Accept: application/json;odata.metadata=minimal
Accept-Charset: UTF-8
User-Agent: Microsoft ADO.NET Data Services
Host: canws212:23890
Connection: Keep-Alive
响应
HTTP/1.1 400 Bad Request
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; odata.metadata=minimal; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
OData-Version: 4.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcRGF5Zm9yY2VcU291cmNlXFJlcG9zXE9EYXRhU2FtcGxlc1xTY2VuYXJpb3NcVHJpcFBpblxzcmNcd2ViYXBpXE9EYXRhU2FtcGxlcy5XZWJBcGlTZXJ2aWNlXFBlb3BsZQ==?=
X-Powered-By: ASP.NET
Date: Sat, 23 Jul 2016 01:23:41 GMT
Content-Length: 1604
{
"error":{
"code":"","message":"The query specified in the URI is not valid. The method or operation is not implemented.","innererror":{
"message":"The method or operation is not implemented.","type":"System.NotImplementedException","stacktrace":" at Microsoft.OData.Core.UriParser.Visitors.QueryNodeVisitor`1.Visit(CountNode nodeIn)\r\n at Microsoft.OData.Core.UriParser.Semantic.CountNode.Accept[T](QueryNodeVisitor`1 visitor)\r\n at System.Web.OData.Query.ParameterAliasNodeTranslator.Visit(BinaryOperatorNode nodeIn)\r\n at Microsoft.OData.Core.UriParser.Semantic.BinaryOperatorNode.Accept[T](QueryNodeVisitor`1 visitor)\r\n at System.Web.OData.Query.FilterQueryOption.get_FilterClause()\r\n at System.Web.OData.Query.Validators.FilterQueryValidator.Validate(FilterQueryOption filterQueryOption, ODataValidationSettings settings)\r\n at System.Web.OData.Query.FilterQueryOption.Validate(ODataValidationSettings validationSettings)\r\n at System.Web.OData.Query.Validators.ODataQueryValidator.Validate(ODataQueryOptions options, ODataValidationSettings validationSettings)\r\n at System.Web.OData.Query.ODataQueryOptions.Validate(ODataValidationSettings validationSettings)\r\n at System.Web.OData.EnableQueryAttribute.ValidateQuery(HttpRequestMessage request, ODataQueryOptions queryOptions)\r\n at System.Web.OData.EnableQueryAttribute.ExecuteQuery(Object response, HttpRequestMessage request, HttpActionDescriptor actionDescriptor)\r\n at System.Web.OData.EnableQueryAttribute.OnActionExecuted(HttpActionExecutedContext actionExecutedContext)"
}
}
}
有什么问题?这是TripPin示例应用程序的缺陷还是我做错了什么?我该如何解决?
修改
我希望在数据库本身进行过滤。即首先获取所有Person实体然后过滤掉的情况远非理想。
答案 0 :(得分:0)
运行c#代码
时dc.People.AddQueryOption("$expand", "Trips").Where(p => p.Trips.Count() > 1).First();
Odata.Client API将查询转换为URL。
您的案例中生成的网址是:
http://canws212:23890/People?$filter=Trips/$count gt 1&$top=1&$expand=Trips
与OData V4的URL约定不匹配
$ filter仅适用于类(People)的属性,而类People不能使用$ filter关键字导航到类Trip,并且没有属性计数。
您可以通过关键字Expand
扩展Trips阅读有关OData版本4.0的更多信息。网址约定:
http://docs.oasis-open.org/odata/odata/v4.0/odata-v4.0-part2-url-conventions.html
所以,您收到错误消息
<强> EDIT2:强>
让第一个Person实体拥有多个Trip
(我用网址测试:http://services.odata.org/V4/TripPinServiceRW)
var dc = new DefaultContainer(new Uri("http://canws212:23890"));
var firstPerson = dc.People.AddQueryOption("$expand", "Trips")
.ToList()
.FirstOrDefault(p => p.Trips.Count > 1);
Console.WriteLine("{0} have: {1} trip", firstPerson.FirstName, firstPerson.Trips.Count);
//The result: Russell have: 3 trip
编辑:3 如果您查看示例28,请在网址中
http://docs.oasis-open.org/odata/odata/v4.0/odata-v4.0-part2-url-conventions.html
Example 28: entity count in a $filter expression.
http://host/service/Categories?$filter=Products/$count gt 0
您发现V4支持计数属性 所以,我的结论
TripPin演示网站不符合URL Convention V4
并且您的查询有效,但无法执行(无计数支持)
http://canws212:23890/People?$filter=Trips/$count gt 1&$top=1&$expand=Trips