Pogo69's Blog

April 5, 2012

CRM LINQ Provider – Converting Expressions to QueryExpression and/or FetchXml

Filed under: Cutting Code — pogo69 [Pat Janes] @ 16:59

Overview

Yet another post for which the impetus was a question posed on the MSDN Support Forums for CRM.

This time, someone wanted to know if a CRM LINQ query could be converted to its QueryExpression and/or its FetchXml equivalent:

http://social.msdn.microsoft.com/Forums/en/crm/thread/8c5fe0fd-d55b-41ea-a0b2-a703eccf06f1

As always, I love a challenge, so I opened up my favourite decompiler and got to work trying to figure out:

  1. How the SDK converts an Expression (the internal representation of a LINQ Query and its constituent parts) to a QueryExpression
  2. How I might convince said SDK method(s) to do the same thing for me

QueryProvider

The results of my investigations turned up the QueryProvider class, that exposes the very method I required (Translate):

namespace Microsoft.Xrm.Sdk.Linq
{
 internal class QueryProvider : IQueryProvider
{
  public QueryExpression Translate(Expression expression)
  {
   Projection projection = null;
   bool flag;
   bool flag1;
   NavigationSource navigationSource = null;
   List<LinkLookup> linkLookups = null;
   return this.GetQueryExpression(expression, out flag, out flag1, out projection, ref navigationSource, ref linkLookups);
  }
 }
}

Awesome!!  Except…

…the QueryProvider class is marked internal.  So I can’t get to it.

One can get at a CRM LINQ query’s QueryProvider via the Provider property:

var contacts =
 (
  from c in xrm.ContactSet
  where c.LastName.StartsWith("B")
  select new Xrm2011.Contact
  {
   FirstName = c.FirstName,
   LastName = c.LastName,
   ParentCustomerId = c.ParentCustomerId
  }
 );
IQueryProvider queryProvider = contacts.Provider;

As you can see the Provider property is exposed via its interface (IQueryProvider) rather than the underlying QueryProvider object – it has to be in fact, as QueryProvider is unavailable outside of the Microsoft.Xrm.Sdk.dll assembly

Reflection to the Rescue!!

NB: WARNING – this is highly unsupported and may break at any time in the future without prior warning!!

Luckily; provided your code has sufficient privileges, reflection allows us to obtain access to fields, properties and methods that are otherwise hidden from us due to access modifiers such as internal.

Thus, to convert your CRM LINQ queries to QueryExpression and/or FetchXml, you may use the following:

var contacts =
 (
  from c in xrm.ContactSet
  where c.LastName.StartsWith("B")
  select new Xrm2011.Contact
  {
   FirstName = c.FirstName,
   LastName = c.LastName,
   ParentCustomerId = c.ParentCustomerId
  }
 );

IQueryProvider queryProvider = contacts.Provider;

MethodInfo translateMethodInfo = queryProvider.GetType().GetMethod("Translate");
QueryExpression query = (QueryExpression)translateMethodInfo.Invoke(queryProvider, new object[] { contacts.Expression });

QueryExpressionToFetchXmlRequest reqConvertToFetchXml = new QueryExpressionToFetchXmlRequest { Query = query };
QueryExpressionToFetchXmlResponse respConvertToFetchXml = (QueryExpressionToFetchXmlResponse)xrm.Execute(reqConvertToFetchXml);

System.Diagnostics.Debug.Print(respConvertToFetchXml.FetchXml);

Conclusion

Enjoy!!  But be careful…

Thanks to sebastian.mayer.67 for the inspiration.

 

Advertisements

3 Comments »

  1. […] Converting Expressions to QueryExpression […]

    Pingback by FetchXml vs. QueryExpression - Random Musings from Bill Ryan | Random Musings from Bill Ryan — October 31, 2012 @ 15:16

  2. […] Converting Expressions to QueryExpression […]

    Pingback by FetchXml vs. QueryExpression : Dynamics Four — March 24, 2013 @ 12:32

  3. […] Converting Expressions to QueryExpression […]

    Pingback by FetchXml vs. QueryExpression | dynamics four — June 28, 2013 @ 13:42


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: