This is a migrated thread and some comments may be shown as answers.

LINQ Expression Tree Serialization

5 Answers 965 Views
Feature Requests
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Pål
Top achievements
Rank 1
Pål asked on 25 Jan 2010, 10:59 PM

Hi.

An excellent feature, which I really miss and think would be absolutely fabolus, is the abillity to serialize LINQ Expression trees.

In n-tier applications this would play out as follows:

1. A client creates a LINQ query for all clients

var result = from c in scope.Extent<Client>() select c; 

2. The expression is serialized
XElement xmlExpression = new ExpressionSerializer().Serialize(result.Expression); 

3. Using whatever means of transportation, the serialized xml expression is sent to the server.
ObjectContainer container = Server.Extent<Client>.Execute(xmlExpression); 

4. On the server side, the xml expression is replayed, filled in an object container and returned to the client.
// Deserialize the xml expression tree  
Expression expression = new ExpressionSerializer().Deserialize(xmlExpression);  
 
// Execute expression  
var result = objectScope.Extent<T>().Provider.Execute<T>(expression);  
 
// Copy result into an object container  
objectContainer.copyFrom(objectScope, "Items", result.ToList<T>, null);  
 
// Return the object Container  
return objectContainer; 

I have played some around with this, but it fails on deserialization since it's impossible to create instances of "Telerik.OpenAccess.Query.ExtentQueryImpl<T>" unless you work at Telerik...

Check out this link at MSDN blogs. They have already created ways to do this, and it contains source code and samples.
Expression Tree Serialization

Waiting in anticipation.

Thanks

Pål

5 Answers, 1 is accepted

Sort by
0
Jordan
Telerik team
answered on 26 Jan 2010, 03:39 PM
Hi Pål,

It just occurred to me that although you cannot serialize the whole OpenAccess query, you can serialize the smaller expressions that are used to build it. These smaller expressions are the projection expression used in the Select extension method, the predicate expression used by the Where extension method, etc.

In this way you should be able to serialize the expressions from which you will later be able to easily construct the query like in the code sample bellow:
ExpressionSerializer serializer = new ExpressionSerializer();
XElement predicateXml = serializer.Serialize(filter);
// persist the serialized expression
 
// some more code
 
// load the serialized expression
filter = serializer.Deserialize<Func<Customer, bool>>(predicateXml);
 
IObjectScope objectScope = ObjectScopeProvider1.GetNewObjectScope();
IQueryable<Customer> query = objectScope.Extent<Customer>().Where(filter);
IList<Customer> customers = query.ToList();

I hope this helps.

All the best,
Jordan
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
0
Pål
Top achievements
Rank 1
answered on 26 Jan 2010, 06:31 PM
Hi!

Thanks for the reply, but I'm not quite sure how to retrieve the "filter" you are talking about. I have tried using the .Expression property of the query and serialize this, but that failes.

Could you give an example on how to retrieve the "filter".

Thanks

Pål
0
Jordan
Telerik team
answered on 27 Jan 2010, 04:02 PM
Hi Pål,

In the code from my previous post the filter parameter is defined earlier in the code as:
Expression<Func<Customer, bool>> filter = c => c.City.StartsWith("S");

Of course in your case the way of defining the predicate expressions may be different.
Can you please share more details with us?

All the best,
Jordan
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
0
Pål
Top achievements
Rank 1
answered on 27 Jan 2010, 04:56 PM
Hi!

Certainly, I'm trying to serialize a complete Expression tree obtained from objectScope.Extent<T>().

The expression could be anything, depending on the LINQ query entered by the developer in the presentation layer.

For this thread, i used as an example the LINQ query:
var query = from c in objectScope.Extent<Client>()  
            select c; 

which when "query.Expression" is serialized to XML, produces the following output:
<MethodCallExpression NodeType="Call">  
  <Method MemberType="Method" MethodName="Select">  
    <DeclaringType> 
      <Type Name="System.Linq.Queryable" /> 
    </DeclaringType> 
    <Parameters> 
      <Type> 
        <Type Name="System.Linq.IQueryable`1">  
          <Type Name="Navita.Client" /> 
        </Type> 
      </Type> 
      <Type> 
        <Type Name="System.Linq.Expressions.Expression`1">  
          <Type Name="System.Func`2">  
            <Type Name="Navita.Client" /> 
            <Type Name="Navita.Client" /> 
          </Type> 
        </Type> 
      </Type> 
    </Parameters> 
    <GenericArgTypes> 
      <Type> 
        <Type Name="Navita.Client" /> 
      </Type> 
      <Type> 
        <Type Name="Navita.Client" /> 
      </Type> 
    </GenericArgTypes> 
  </Method> 
  <Object /> 
  <Arguments> 
    <ConstantExpression NodeType="Constant">  
      <Value>Extent&lt;Navita.Client&gt;</Value> 
      <Type> 
        <Type Name="Telerik.OpenAccess.Query.ExtentQueryImpl`1">  
          <Type Name="Navita.Client" /> 
        </Type> 
      </Type> 
    </ConstantExpression> 
    <UnaryExpression IsLifted="false" IsLiftedToNull="false" NodeType="Quote">  
      <Operand> 
        <LambdaExpression NodeType="Lambda">  
          <Body> 
            <ParameterExpression Name="c" NodeType="Parameter">  
              <Type> 
                <Type Name="Navita.Client" /> 
              </Type> 
            </ParameterExpression> 
          </Body> 
          <Parameters> 
            <ParameterExpression Name="c" NodeType="Parameter">  
              <Type> 
                <Type Name="Navita.Client" /> 
              </Type> 
            </ParameterExpression> 
          </Parameters> 
          <Type> 
            <Type Name="System.Func`2">  
              <Type Name="Navita.Client" /> 
              <Type Name="Navita.Client" /> 
            </Type> 
          </Type> 
        </LambdaExpression> 
      </Operand> 
      <Method /> 
      <Type> 
        <Type Name="System.Linq.Expressions.Expression`1">  
          <Type Name="System.Func`2">  
            <Type Name="Navita.Client" /> 
            <Type Name="Navita.Client" /> 
          </Type> 
        </Type> 
      </Type> 
    </UnaryExpression> 
  </Arguments> 
  <Type> 
    <Type Name="System.Linq.IQueryable`1">  
      <Type Name="Navita.Client" /> 
    </Type> 
  </Type> 
</MethodCallExpression> 

This is all fine and it can be transferred accross the wire to the business layer.

However, on she server side, this needs to be deserialized into a query/expression which can be processed by OpenAccess, and if you take a look at this part of the XML:
    <ConstantExpression NodeType="Constant">  
      <Value>Extent&lt;Navita.Client&gt;</Value> 
      <Type> 
        <Type Name="Telerik.OpenAccess.Query.ExtentQueryImpl`1">  
          <Type Name="Navita.Client" /> 
        </Type> 
      </Type> 
    </ConstantExpression> 
It requires the creation of a "Telerik.OpenAccess.Query.ExtentQueryImpl<T>".
I did however, find a way to hook into the deserialization process and instantiate the type using "Telerik.OpenAccess.ExtensionMethods.Extent<T>(IObjectScope scope)" method.

I Have only tried some simple LINQ queries, but will try and test some more.

You wouldn't happen to have a set of LINQ 101 test for c# so I can run some tests?

Anyway, I'll be happy to post any findings and how to extend the soultion (see link above) to work with OA.

Regards

Pål
0
Jordan
Telerik team
answered on 28 Jan 2010, 09:23 AM
Hello Pål,

What we have is a sample application that demonstrates the LINQ 101 queries with OpenAccess.
You can find it here:
http://www.telerik.com/community/code-library/orm/general/telerik-openaccess-orm-1-1-linq-samples.aspx

I guess that if you modify it a little you could use it for your tests.
It will be great if you can share your findings with the community.

Regards,
Jordan
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
Tags
Feature Requests
Asked by
Pål
Top achievements
Rank 1
Answers by
Jordan
Telerik team
Pål
Top achievements
Rank 1
Share this question
or