WCF Data Services 5.2.0-rc1 Prerelease

A couple of days ago we posted a new set of NuGet packages and today we posted a new tools installer for WCF Data Services 5.2.0-rc1. This prerelease integrates the UriParser from ODataLib Contrib and fixes a few bugs.

What is in the prerelease

This prerelease contains the following noteworthy bug fixes:

  • Fixes an issue where code gen for exceedingly large models would cause VS to crash
  • Provides a better error message when the service model exposes enum properties
  • Fixes an issue where IgnoreMissingProperties did not work properly with the new JSON format
  • Fixes an issue where an Atom response is unable to be read if the client is set to use the new JSON format

URI Parser

In this release ODataLib now provides a way to parse filter and orderby expressions into a metadata-bound abstract syntax tree (AST). This functionality is typically intended to be consumed by higher level libraries such as WCF Data Services and Web API.

To parse a filter expression, use the following method on the new class ODataUriParser:

public static FilterClause ParseFilter(
string filter,
IEdmModel model,
IEdmType elementType,
IEdmEntitySet entitySet)

The ParseFilter method returns a FilterClause object. The Expression property on the FilterClause contains the root node of the AST that represents the filter expression. In order to walk the AST, use the Visitor pattern to handle an arbitrary QueryNode by examining the Kind property, and then casting accordingly. For instance:

switch (node.Kind)
{
case QueryNodeKind.BinaryOperator:
return Visit((BinaryOperatorNode)node);
case QueryNodeKind.UnaryOperator:
return Visit((UnaryOperatorNode)node);
case QueryNodeKind.SingleValuePropertyAccess:
return Visit((SingleValuePropertyAccessNode)node);
// And so on...
}

Let’s say the filter string was "Name eq 'Bob'", and Name is a property on the elementType provided to ParseFilter.  This expression is represented by a BinaryOperatorNode. The BinaryOperatorNode has a Left expression, which is a SingleValuePropertyAccessNode, capturing the Name property, and a Right expression, which is a ConstantNode, capturing the string literal 'Bob'. 

To parse an orderby expression, use ODataUriParser.ParseOrderBy. This method is very similar to ParseFilter. The resulting OrderByClause also has an Expression property, which is an AST just like FilterClause. Since an $orderby system query option can specify more than one ordering expression, there is a ThenBy property on OrderByClause that points to the next OrderByClause. So in essence, you get a linked list of OrderByClause objects. For example, the string "Name asc, ShoeSize desc" would result in an OrderByClause with an Expression capturing the Name property, and a ThenBy property pointing to another OrderByClause capturing the intent to order by the ShoeSize in descending order.

For a more detailed write-up on filter and orderby parsing, read this blog post.

Feedback Please

We’d love to hear how well this release works for your service. Even if you don’t need the URI Parser functionality, please consider trying these new bits and providing us with feedback whether everything goes perfectly or you run into problems. As always, please feel free to leave a comment below or e-mail me directly at mastaffo@microsoft.com.

Comments

  • Anonymous
    December 10, 2012
    Hi, It seems that when requesting JSON format, any Syndication mapped properties are injected in the select part of the expression that is passed to my DataServiceQueryProvider. This must be something that should be optimized. The syndication properties are not used in a JSON payload, so why would they get injected in the expression tree? Kind regards Uffe

  • Anonymous
    December 10, 2012
    Hi, I tried to add this comment earlier, but it never showed up. In my scenario the JSON format actually performs worse than ATOM when everything is taken into account. As far as I can tell it is due to desiralizing on the client of the JSON payload being less efficient than desiralizing ATOM. In my setup the factor is around 2 in favour of ATOM, and seems to increase as more properties are transfered. Could we ecpect this to be optimized by the time of RTM? Kind regards Uffe

  • Anonymous
    December 17, 2012
    @Uffe - Sorry that it's taken me so long to get back to you. We do expect that the actual process of deserializing JSON will be more expensive than deserializing Atom because of the complexity required in calculating the missing information. I don't think we expect a ratio of 2:1, so maybe we can sync up offline to see what you're looking at in detail. Performance is something we're starting to make more time for in general - over the next few months we have increasing amounts of resource time for looking at our performance hotspots. We've delivered a lot of new functionality recently, now it's time to improve the stability and performance of that functionality.

  • Anonymous
    July 25, 2013
    Nice information its useful