如何使用生成的C#OData客户端代码请求具有多于1个嵌套实体的实体?

时间:2016-07-23 01:35:03

标签: c# odata

我正在使用来自https://github.com/OData/ODataSamples/tree/master/Scenarios/TripPin/src/webapi的TripPin OData演示,使用由以下VS扩展引入的OData模板生成的OData C#客户端代码:enter image description here

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实体然后过滤掉的情况远非理想。

1 个答案:

答案 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