Serialize LINQ Expressions over WCF

I like LINQ expression - a lot. It makes my life so much easier when querying data. But LINQ expressions have (at least) one drawback: they are not serializable. But think about it, wouldn't be awesome to define your expressions on the client side, and get them executed on the server? I thought so, that's why i wrote Serialize.Linq.

Let's get started with a quick example:

        [DataContract]
        public class Person
        {
                [DataMember]
                public string FirstName { get; set; }
                
                [DataMember]
                public string LastName { get; set; }
        }
        
        [ServiceContract]
        public interface IPersonService
        {
                [OperationContract]
                Person[] GetAllPersons();               
        }

It's a simple DataContract over persons. Retrieving all persons is easy: just call the provided GetAllPersons functions:

        var persons = _personService.GetAllPersons();

But what if you want to query persons by their last name? You need to add another OperationContract:

        [ServiceContract]
        public interface IPersonService
        {
                [OperationContract]
                Person[] GetAllPersons();               
                
                [OperationContract]
                Person[] QueryPersonsByLastName(string lastName);
        }

This is okay as long as you want to search for persons by there actually last name. But as reality proves, queries are often much more complicated, and it can be a hassle to change the service interface to satisfy the needs of every client or user and any business case.

It would be much easier to provide a generic interface that uses an expression to query persons:

        [OperationContract]
        Perons[] QueryPersons(Expression<Func<Person, bool>> query);

But that is not going to work because Expressions are not serializable. Now, it is time to introduce Serialize.Linq. To achieve the above behaviour, we need to make some small modifictions:

        using Serialize.Ling;
        using Serialize.Ling.Nodes;

        [OperationContract]
        Perons[] QueryPersons(ExpressionNode query);

Converting an Expression to an ExpressionNode and vice versa

The simplest way to convert any LINQ expression to an ExpressionNode is to use the extension method ToExpressionNode.

        using Serialize.Ling;
        using Serialize.Ling.Extensions;
        using Serialize.Ling.Nodes;

        var expression = (Expression<Func<Person, bool>>)(person 
                => person.LastName == "Miller" 
                && person.FirstName.StartsWith("M"));
        var expressionNode = expression.ToExpressionNode();

Converting back to an expression is as simple:

        var expression = expressionNode.ToExpression<Func<Person, bool>>();

And that is already it. Now you have pretty much everything you need to get started using LINQ expressions in your WCF services.

Feel free to comment and share it if you like it.

Comments

blog comments powered by Disqus