Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Black Art – LINQ expressions reuse

, 9 Aug 2012
When developing a complex line of business system queries, reuse is often required. This article provides some guidelines and tools for LINQ expressions reuse.
LinqExpressionsReuse_v1.0.zip
LinqExpressionProjection
bin
Debug
LinqExpressionProjection.dll
LinqExpressionProjection.pdb
Release
LinqExpressionProjection.csproj.vspscc
obj
Debug
DesignTimeResolveAssemblyReferencesInput.cache
LinqExpressionProjection.dll
LinqExpressionProjection.pdb
TempPE
Properties
LinqExpressionProjection.Test
bin
Debug
Dependencies
EntityFramework.dll
EntityFramework.dll
LinqExpressionProjection.dll
LinqExpressionProjection.pdb
LinqExpressionProjection.Test.dll
LinqExpressionProjection.Test.pdb
Release
Dependencies
EntityFramework.dll
LinqExpressionProjection.Test.csproj.vspscc
Model
obj
Debug
DesignTimeResolveAssemblyReferencesInput.cache
LinqExpressionProjection.Test.dll
LinqExpressionProjection.Test.pdb
ResolveAssemblyReference.cache
TempPE
Properties
LinqExpressionsReuse
bin
Debug
EF_ReuseLinq.exe
EF_ReuseLinq.pdb
EF_ReuseLinq.vshost.exe
EF_ReuseLinq.vshost.exe.manifest
EntityFramework.dll
LinqExpressionProjection.dll
LinqExpressionProjection.pdb
Dependencies
EntityFramework.dll
EF_ReuseLinq.csproj.user
Model
obj
x86
Debug
DesignTimeResolveAssemblyReferencesInput.cache
EF_ReuseLinq.exe
EF_ReuseLinq.pdb
ResolveAssemblyReference.cache
TempPE
Properties
TestResults
Asher_PC1600 2012-06-12 16_37_14.trx
Asher_PC1600 2012-06-12 16_37_14
Out
EntityFramework.dll
LinqExpressionProjection.dll
LinqExpressionProjection.pdb
linqexpressionprojection.test.dll
LinqExpressionProjection.Test.pdb
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Collections;

namespace LinqExpressionProjection
{
	/// <summary>
	/// An IQueryable wrapper that allows us to visit the query's expression tree just before LINQ to SQL gets to it.
	/// This is based on the excellent work of Tomas Petricek: http://tomasp.net/blog/linq-expand.aspx
	/// </summary>
	public class ProjectionSupportingQuery<T> : IQueryable<T>, IOrderedQueryable<T>, IOrderedQueryable
	{
        ProjectionSupportingQueryProvider<T> _provider;
		IQueryable<T> _inner;

		internal IQueryable<T> InnerQuery { get { return _inner; } }			// Original query, that we're wrapping

        internal ProjectionSupportingQuery(IQueryable<T> inner)
		{
			_inner = inner;
            _provider = new ProjectionSupportingQueryProvider<T>(this);
		}

		Expression IQueryable.Expression { get { return _inner.Expression; } }
		Type IQueryable.ElementType { get { return typeof (T); } }
		IQueryProvider IQueryable.Provider { get { return _provider; } }
		public IEnumerator<T> GetEnumerator () { return _inner.GetEnumerator (); }
		IEnumerator IEnumerable.GetEnumerator () { return _inner.GetEnumerator (); }
		public override string ToString () { return _inner.ToString (); }
	}

	class ProjectionSupportingQueryProvider<T> : IQueryProvider
	{
        ProjectionSupportingQuery<T> _query;

        internal ProjectionSupportingQueryProvider(ProjectionSupportingQuery<T> query)
		{
			_query = query;
		}

		// The following four methods first call ExpressionExpander to visit the expression tree, then call
		// upon the inner query to do the remaining work.

		IQueryable<TElement> IQueryProvider.CreateQuery<TElement> (Expression expression)
		{
            return new ProjectionSupportingQuery<TElement>(_query.InnerQuery.Provider.CreateQuery<TElement>(expression.ExpandExpressionsForProjection()));
		}

		IQueryable IQueryProvider.CreateQuery (Expression expression)
		{
			return _query.InnerQuery.Provider.CreateQuery (expression.ExpandExpressionsForProjection());
		}

		TResult IQueryProvider.Execute<TResult> (Expression expression)
		{
            return _query.InnerQuery.Provider.Execute<TResult>(expression.ExpandExpressionsForProjection());
		}

		object IQueryProvider.Execute (Expression expression)
		{
            return _query.InnerQuery.Provider.Execute(expression.ExpandExpressionsForProjection());
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)

Share

About the Author

Asher Barak
Software Developer Ziv systems, Israel
Israel Israel
Starting with Apple IIe BASICA, and working my way through Pascal, Power Builder, Visual basic (and the light office VBA) C, C++, I am now a C# .NET developer and designer (and a big fan of the .NET framework).
 
I am currently leading a major effort writing a new framework for SAP Business One extensions and overseeing the development of four products on the same (yet unfinished) framework

| Advertise | Privacy | Mobile
Web01 | 2.8.140821.2 | Last Updated 9 Aug 2012
Article Copyright 2012 by Asher Barak
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid