In my app I have some queries that use the same repeated logic:
var someThings = context.table1
.where(SomeLogic)
.ToList();
With EF Core 2.1 I could encapsulate this logic in a layer with all these expressions:
public static Expression<Func<MyObject, bool>> SomeLogic =>
myObject => myObject.CreationDate.Date == DateTime.Now.Date
&& (myObject.Whatever.HasValue || myObject.MoreWhatever);
Now I discovered this was being evaluated in memory, and that's bad.
If I do something like:
var someThings = context.table1
.where(myObject =>
myObject.CreationDate.Date == DateTime.Now.Date
&& (myObject.Whatever.HasValue || myObject.MoreWhatever))
.ToList();
then the query is evaluated in the DB, but I am putting some logic in the wrong layer.
I tried to subsitute Expression with a function or any other tool, but I don't find a way to do it.
Is there a way to encapsulate the logic of a query in a layer as I was doing before, but preserving EF rules so that this query can still be evaluated in the DB?
Thanks.
Why you need a "real" expression and not just a Lambda is explained in this answer. The created Expression can be created anywhere and passed as a parameter to the function that executes the query.
This answer should guide the way you need to go. You only have to replace the two dummy expressions with the whatever.hasvalue...stuff
I had the most trouble with Expression.PropertyOrField. If you have nested structures you need to loop through the data structure and call Expression.PropertyOrField with the first parameter being the result from the previous call to Expression.PropertyOrField.