Search code examples
c#.netwcf-data-servicesodatanetflix

Netflix OData: Simple query using the 'Count' of a navigation property


I am getting to know OData by querying existing OData feeds using LINQPad. Using the Netflix feed, I am attempting to get a list of actors with the most awards, but I am getting strange exceptions. My first attempt was:

People.OrderByDescending(p => p.Awards.Count).Take(10)

But that gave me a 5DataServiceQueryException with an inner exception of:

No property 'Count' exists in type 'System.Collections.Generic.ICollection`1[[Netflix.Catalog.v2.Entities.TitleAward, Netflix.Catalog.v2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' at position 7.

I tried to change things a little, by using the .Count() extension method instead of the .Count property:

People.OrderByDescending(p => p.Awards.Count()).Take(10)

But that just game me an InvalidCastException:

Unable to cast object of type 'System.Linq.Expressions.PropertyExpression' to type 'System.Data.Services.Client.ResourceExpression'.

at System.Data.Services.Client.ResourceBinder.AnalyzeCountMethod(MethodCallExpression mce)
at System.Data.Services.Client.ResourceBinder.VisitMethodCall(MethodCallExpression mce)
at System.Data.Services.Client.ALinqExpressionVisitor.Visit(Expression exp)
at System.Data.Services.Client.DataServiceALinqExpressionVisitor.Visit(Expression exp)
at System.Data.Services.Client.ALinqExpressionVisitor.VisitLambda(LambdaExpression lambda)
at System.Data.Services.Client.ALinqExpressionVisitor.Visit(Expression exp)
at System.Data.Services.Client.DataServiceALinqExpressionVisitor.Visit(Expression exp)
at System.Data.Services.Client.ALinqExpressionVisitor.VisitUnary(UnaryExpression u)
at System.Data.Services.Client.ALinqExpressionVisitor.Visit(Expression exp)
at System.Data.Services.Client.DataServiceALinqExpressionVisitor.Visit(Expression exp)
at System.Data.Services.Client.ALinqExpressionVisitor.VisitExpressionList(ReadOnlyCollection1 original)
at System.Data.Services.Client.ALinqExpressionVisitor.VisitMethodCall(MethodCallExpression m)
at System.Data.Services.Client.ResourceBinder.VisitMethodCall(MethodCallExpression mce)
at System.Data.Services.Client.ALinqExpressionVisitor.Visit(Expression exp)
at System.Data.Services.Client.DataServiceALinqExpressionVisitor.Visit(Expression exp)
at System.Data.Services.Client.ALinqExpressionVisitor.VisitExpressionList(ReadOnlyCollection
1 original)
at System.Data.Services.Client.ALinqExpressionVisitor.VisitMethodCall(MethodCallExpression m)
at System.Data.Services.Client.ResourceBinder.VisitMethodCall(MethodCallExpression mce)
at System.Data.Services.Client.ALinqExpressionVisitor.Visit(Expression exp)
at System.Data.Services.Client.DataServiceALinqExpressionVisitor.Visit(Expression exp)
at System.Data.Services.Client.ResourceBinder.Bind(Expression e)
at System.Data.Services.Client.DataServiceQueryProvider.Translate(Expression e)
at System.Data.Services.Client.DataServiceQuery1.Execute()
at System.Data.Services.Client.DataServiceQuery
1.GetEnumerator()
at System.Data.Services.Client.DataServiceQuery`1.System.Collections.IEnumerable.GetEnumerator()

I tried to follow the suggestions at this question but all I got is one of the above two errors.

Any ideas how to perform this simple operation?


Solution

  • You are wanting to make a decision (in this case "order"), based on an aggregate operation (count).
    That kind of aggregate operation is not supported in OData queries (for now?).

    See this this question for more information: Collection Exists Criteria in WCF Data Services

    In the end, you would have to deal with filtering/ordering the data in a different way. At least 2 possible solutions:

    1. Pull more data down to the client, and filter it there.
    2. If you control the server, then you can expose a specialized service operation to return the result (obviously not the case when Netflix is your data source)