Sharing the where clause between LINQ statements

I have several LINQ-to-Entities queries that fall into the same two tables and have the same conditions. What I'm trying to do is share the where clause between multiple requests. For example, let's say I have this:

from t0 in db.Table0 from t1 in db.Table1 from t2 in db.Table2 where t0.Field7 == 'something' && t1.Field1 > t2.Field3 && t2.NavigationProperty(t => t.Field4 == t1.Field2).Any() select t0 

I would like to say something like this:

 Func<Table1, Table2, bool> specialCondition = (t1, t2) => t1.Field1 > t2.Field3 && t2.NavigationProperty(t => t.Field4 == t1.Field2).Any(); from t0 in db.Table0 from t1 in db.Table1 from t2 in db.Table2 where t0.Field7 == 'something' && specialCondition(t1, t2) select t1 

This generates The LINQ expression node type 'Invoke' is not supported in LINQ to Entities. that makes sense. It cannot parse arbitrary .NET function / delegate code into something that it can pass to the database.

Everything I read on the Internet says that expression trees, however, may work just fine. My problem is that I can declare it (it is almost the same syntax as the function), I do not know how to use it.

 Expression<Func<Table1, Table2, bool>> specialCondition = (t1, t2) => t1.Field1 > t2.Field3 && t2.NavigationProperty(t => t.Field4 == t1.Field2).Any(); 

What should I do with this? How to pass it LINQ2EF?

Update: A working solution with LinqKit in accordance with the @Mic recommendation, derived from NuGet (note the .AsExpandable() and .Invoke and the edited imported reference and LinqKit namespace):

 Expression<Func<Table1, Table2, bool>> specialCondition = (t1, t2) => t1.Field1 > t2.Field3 && t2.NavigationProperty(t => t.Field4 == t1.Field2).Any(); from t0 in db.Table0.AsExpandable() from t1 in db.Table1 from t2 in db.Table2 where t0.Field7 == 'something' && specialCondition.Invoke(t1, t2) select t1 

Validation in LinqPad, both the first fully integrated version and the final version of Exq LinqKit express the same SQL and results. Many thanks to all of you for your suggestions and help.

+4
source share
3 answers

Such constructs are not possible in the native provider L2S / L2Entities. You should use the LINQKit library, which supports the extension of the expression.

+3
source

Create a delegate using CompiledQuery . I am sure it works in LINQ for Entities. You just need to include the DataContext type as the first parameter.

 Func<MyDataContext, Table1, Table2, bool> specialCondition = CompiledQuery.Create( (MyDataContext dc, Table1 t1, Table2 t2) => t1.Field1 > t2.Field3 && t2.NavigationProperty(t => t.Field4 == t1.Field2).Any()); 

Then, to use it, you must be able to do this:

 var query = from t0 in db.Table0 from t1 in db.Table1 from t2 in db.Table2 where t0.Field7 == 'something' && specialCondition(db, t1, t2) select t1 
+1
source

Rewrite your LINQ query into LINQ expression syntax and pass the expression to Where(expression) .

0
source

Source: https://habr.com/ru/post/1386423/


All Articles