I want to make parts of a LINQ query reusable by using expression trees (i think that's how its called).
Here's a simplified version of my query:
var lQuery =
from m in ...
join a in ... into ta
from ra in ta.DefaultIfEmpty()
select
new {
...
Status = ra != null ? ... : ..., /* <- i want this to be reusable */
...
};
As you can see, the value of Status is determined via ? :
syntax which is translated by LINQ automatically (a expression tree i suppose, the SQL logs show a CASE WHEN
query in the end).
How do i move that code to a separate function so that my application does not throw a not supported
exception at runtime?
I tried adding a function
public static System.Linq.Expressions.Expression<System.Func<%type of ra%, %status type%>>
QueryStatusExpression()
{
return ra => ra != null ? ... : ...;
}
then use it like
Status = QueryStatusExpression().Invoke(ra)
but it throws the not supported
exception.
I'm out of ideas right now. Any help is appreciated.
The issue can be solved via combined expressions
of the LINQKit project.
Here's how to do it:
Add the LinqKit
reference to your project (e.g. via NuGet package manager).
Add the following line on top of your .cs file to make the extension methods of LINQKit available
using LinqKit; // for System.Linq.Expressions.Expression<>.Invoke()
Define the expression as a static field
public static System.Linq.Expressions.Expression<
System.Func<%type of ra% ra, %status type%>>
GetStatusExpression = ra != null ? ... : ...;
Invoke the expression in the query (be sure to add .AsExpandable() to the first table as described in the LINQKit docs)
var lQuery =
from m in %first table%.AsExpandable() ...
join a in ... into ta
from ra in ta.DefaultIfEmpty()
select
new {
...
Status = GetStatusExpression.Invoke(ra),
...
};
If you want to use the expression in "normal" code then you need to compile it first like
public static System.Func<%type of ra% ra, %status type%>
GetStatusExpressionCompiled = GetStatusExpression.Compile();
...
if (GetStatusExpressionCompiled(ra) == ...)
{
...
Big thanks goes to svick for pointing me in the right direction with it's comment.