{"id":1308,"date":"2014-02-13T21:20:01","date_gmt":"2014-02-13T21:20:01","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=1308"},"modified":"2014-02-13T21:21:14","modified_gmt":"2014-02-13T21:21:14","slug":"creating-a-custom-linq-provider","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/creating-a-custom-linq-provider\/","title":{"rendered":"Creating a custom Linq Provider"},"content":{"rendered":"<p>To create a custom LINQ provider we need to implement the interfaces, IQueryable or IOrderedQueryable and IQueryProvider. <\/p>\n<p>This is a summary of several posts\/blogs I&#8217;ve read on the subject and source code available on github etc. See References below.<\/p>\n<p><strong>IQueryable&lt;T&gt;<\/strong><\/p>\n<p>To implement a minimal LINQ provider we need to implement IQueryable&lt;&gt;. This interface inherits from IEnumerable. The actual IQueryable methods are minimal<\/p>\n<ol>\n<li>ElementType<\/li>\n<li>Expression<\/li>\n<li>Provider<\/li>\n<\/ol>\n<p><strong>IOrderedQueryable&lt;T&gt;<\/strong><\/p>\n<p>If we want to support the sorting query operators, then we need to implement IOrderedQueryable&lt;T&gt;. <\/p>\n<p>IOrderedQueryable inherits from IEnumerable, IEnumerable&lt;T&gt;, IOrderedQueryable, IQueryable, and IQueryable&lt;T&gt;.<\/p>\n<p>We can implement an IOrderedQueryable that&#8217;s reusable for most situations, as follows<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic class Queryable&lt;T&gt; : IOrderedQueryable&lt;T&gt;\r\n{\r\n   public Queryable(IQueryContext queryContext)\r\n   {\r\n      Initialize(new QueryProvider(queryContext), null);\r\n   }\r\n\r\n   public Queryable(IQueryProvider provider)\r\n   {\r\n     Initialize(provider, null);\r\n   }\r\n\r\n   internal Queryable(IQueryProvider provider, Expression expression)\r\n   {\r\n      Initialize(provider, expression);\r\n   }\r\n\r\n   private void Initialize(IQueryProvider provider, Expression expression)\r\n   {\r\n      if (provider == null)\r\n         throw new ArgumentNullException(&quot;provider&quot;);\r\n      if (expression != null &amp;&amp; !typeof(IQueryable&lt;T&gt;).\r\n             IsAssignableFrom(expression.Type))\r\n         throw new ArgumentException(\r\n              String.Format(&quot;Not assignable from {0}&quot;, expression.Type), &quot;expression&quot;);\r\n\r\n      Provider = provider;\r\n      Expression = expression ?? Expression.Constant(this);\r\n   }\r\n\r\n   public IEnumerator&lt;T&gt; GetEnumerator()\r\n   {\r\n      return (Provider.Execute&lt;IEnumerable&lt;T&gt;&gt;(Expression)).GetEnumerator();\r\n   }\r\n\r\n   System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\r\n   {\r\n      return (Provider.Execute&lt;System.Collections.IEnumerable&gt;(Expression)).GetEnumerator();\r\n   }\r\n\r\n   public Type ElementType\r\n   {\r\n      get { return typeof(T); }\r\n   }\r\n\r\n   public Expression Expression { get; private set; }\r\n   public IQueryProvider Provider { get; private set; }\r\n}\r\n<\/pre>\n<p><em>Note: The IQueryContext is not part of the LINQ interfaces but one I&#8217;ve created to allow me to abstract the actual &#8220;custom&#8221; part of the code and allow maximum reuse of default functionality.<\/em><\/p>\n<p><strong>IQueryProvider<\/strong><\/p>\n<p>The IQueryProvider basically requires two methods (a generic and non-generic version of both) to be implemented. Obviously the generic versions are for strongly typed and the non-generic are loosely typed.<\/p>\n<p><strong>CreateQuery<\/strong><\/p>\n<p>The CreateQuery method is used to create a new instance of an IQueryable based upon the supplied expression tree. <\/p>\n<p><strong>Execute<\/strong> <\/p>\n<p>The Execute method is used to actually execute a query expression, i.e. in a custom provider we will get the data from the datasource, for example a webservice or database etc. and it&#8217;s in the Execute method that we both get the data and do any conversion to, say SQL or the likes (if the LINQ query ultimately queries some other system.<\/p>\n<p>An example of an implementation for an IQueryProvider might look like this&#8230;<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic class QueryProvider : IQueryProvider\r\n{\r\n   private readonly IQueryContext queryContext;\r\n\r\n   public QueryProvider(IQueryContext queryContext)\r\n   {\r\n      this.queryContext = queryContext;\r\n   }\r\n\r\n   public virtual IQueryable CreateQuery(Expression expression)\r\n   {\r\n      Type elementType = TypeSystem.GetElementType(expression.Type);\r\n      try\r\n      {\r\n         return                \r\n            (IQueryable)Activator.CreateInstance(typeof(Queryable&lt;&gt;).\r\n                   MakeGenericType(elementType), new object&#x5B;] { this, expression });\r\n      }\r\n      catch (TargetInvocationException e)\r\n      {\r\n         throw e.InnerException;\r\n      }\r\n   }\r\n\r\n   public virtual IQueryable&lt;T&gt; CreateQuery&lt;T&gt;(Expression expression)\r\n   {\r\n      return new Queryable&lt;T&gt;(this, expression);\r\n   }\r\n\r\n   object IQueryProvider.Execute(Expression expression)\r\n   {\r\n      return queryContext.Execute(expression, false);\r\n   }\r\n\r\n   T IQueryProvider.Execute&lt;T&gt;(Expression expression)\r\n   {\r\n      return (T)queryContext.Execute(expression, \r\n                 (typeof(T).Name == &quot;IEnumerable`1&quot;));\r\n   }\r\n}\r\n<\/pre>\n<p><em>Note: Again, the IQueryContext is not part of the LINQ interfaces but one I&#8217;ve created to allow me to abstract the actual &#8220;custom&#8221; part of the code and allow maximum reuse of default functionality.<\/em><\/p>\n<p><em>The TypeSystem class is taken from the post<a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb546158.aspx\" title=\"Walkthrough: Creating an IQueryable LINQ Provider\" target=\"_blank\"> Walkthrough: Creating an IQueryable LINQ Provider<\/a><\/em><\/p>\n<p><strong>IQueryContext<\/strong><\/p>\n<p>The above shows some LINQ interfaces and some sample implementations. I&#8217;ve pointed out that IQueryContext is not part of LINQ but is instead something I&#8217;ve created (based upon reading various other implementations) to allow me to abstract the actual LINQ provider code specific to my provider&#8217;s implementation. Ofcourse we could have derived from QueryProvider, but for now we &#8220;plug-in&#8221; the data context instead. To change the implementation to derive from QueryProvider simple remove the IQueryContext (also from the Queryable implementation) and override the Execute methods.<\/p>\n<p>For now I&#8217;ll continue this post using the IQueryContext, so here&#8217;s the interface<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic interface IQueryContext\r\n{\r\n   object Execute(Expression expression, bool isEnumerable);\r\n}\r\n<\/pre>\n<p><strong>Implementing the IQueryContext<\/strong><\/p>\n<p>Whether the implementation of the actual Execute code (on the IQueryProvider) is abstracted into the IQueryContext or implemented within an alternate implementation of IQueryProvider. This is where the fun of actually &#8220;running&#8221; the LINQ query against your custom provider takes place. <\/p>\n<p>When writing something like this&#8230;<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar ctx = new Queryable&lt;string&gt;(new CustomContext())\r\n\r\nvar query = from s in ctx where s.StartsWith(&quot;T&quot;) select s;\r\n<\/pre>\n<p>what we are really doing is creating the query. Hence the CreateQuery methods on the IQueryProvider are called, but the actual data source or whatever supplies the data for your custom LINQ provider <strong>should not<\/strong> be called until we reach the execution phase, this is known as deferred execution. The execution phase takes place when we enumerate over the query or call methods, such as Count() etc. against a query.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nforeach (var q in query)\r\n{\r\n   Console.WriteLine(q);\r\n}\r\n<\/pre>\n<p>So at the point that we GetEnumerator implicitly via the foreach loop, that&#8217;s when the Execute method is called.<\/p>\n<p><strong>Executing the query<\/strong><\/p>\n<p>So, the Execute method is called and we will have an expression tree defined by LINQ supplied as an argument. We now need to translate that query into something useful, i.e. turn it into an SQL query for a custom database LINQ provider and then get the data for this query, or get data from a webservice and allow the query to be executed against the returned data etc.<\/p>\n<p>As the actual decoding of the Expression is a fairly large subject in itself, I&#8217;ll leave that for another post, but suffice to say, there&#8217;s a lot we need to implement to duplicate some if not all of the &#8220;standard&#8221; LINQ query operators etc.<\/p>\n<p><strong>References<\/strong><\/p>\n<p><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb546158.aspx\" title=\"Walkthrough: Creating an IQueryable LINQ Provider\" target=\"_blank\">Walkthrough: Creating an IQueryable LINQ Provider<\/a><br \/>\n<a href=\"http:\/\/http:\/\/blogs.msdn.com\/b\/mattwar\/archive\/2008\/11\/18\/linq-links.aspx\" title=\"LINQ: Building an IQueryable provider series\" target=\"_blank\">LINQ: Building an IQueryable provider series<\/a><br \/>\n<a href=\"http:\/\/blogs.msdn.com\/b\/charlie\/archive\/2007\/12\/09\/deferred-execution.aspx\" title=\"LINQ and Deferred Execution\" target=\"_blank\">LINQ and Deferred Execution<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>To create a custom LINQ provider we need to implement the interfaces, IQueryable or IOrderedQueryable and IQueryProvider. This is a summary of several posts\/blogs I&#8217;ve read on the subject and source code available on github etc. See References below. IQueryable&lt;T&gt; To implement a minimal LINQ provider we need to implement IQueryable&lt;&gt;. This interface inherits from [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[49,3,64],"tags":[],"class_list":["post-1308","post","type-post","status-publish","format-standard","hentry","category-net","category-c","category-linq"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/1308","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=1308"}],"version-history":[{"count":29,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/1308\/revisions"}],"predecessor-version":[{"id":1403,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/1308\/revisions\/1403"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=1308"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=1308"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=1308"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}