Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF Core: How to reuse same expression in different query contexts

I have two entity types:

public partial class StudentEntity
{
   public int Age { get; set; }
   
   public int GroupId { get; set; }
}

public partial class GroupEntity
{
   public int Id { get; set; }

   public virtual Collection<StudentEntity> Students { get; set; }
}

and I have an expression which I want to reuse:

Expression<Func<StudentEntity, bool>> isAdult = student => student.Age > 21;

There are two scenarios where I need to use the above expression:

when querying all adult students

IEnumerable<StudentEntity> students = context.Students
                                             .Where(isAdult)
                                             .ToList();

and when querying all groups with at least one adult

IEnumerable<GroupEntity> groups = context.Groups
                                         .Where(g => g.Students
                                                      .Where(isAdult)
                                                      .Any())
                                         .ToList();

The problem is that in the second scenario the Where clause is applied on Collection and it requires a Func<StudentEntity, bool> and not an Expression<Func<StudentEntity, bool>>.

Passing isAdult.Compile() to the Where method leads to a successful compilation but later to an unhandled exception at runtime due to the inability of the framework to translate the compiled into a method expression.

Is there a way to reuse the existing expression in the different querying contexts having the mentioned above entity structure/hierarchy?

like image 701
D. Ivanov Avatar asked Oct 15 '25 16:10

D. Ivanov


1 Answers

Update

I just tested something similar with Entity Framework Core 5 running in LINQPad, and it looks like Jonathan Barclay's suggestion to call .AsQueryable() should work.

IEnumerable<GroupEntity> groups = context.Groups
                                         .Where(g => g.Students
                                                      .AsQueryable()
                                                      .Where(isAdult)
                                                      .Any())
                                         .ToList();

Original Answer

This is a good use case for LINQKit, which would allow you to do this:

IEnumerable<GroupEntity> groups = context.Groups.AsExpandable()
                                         .Where(g => g.Students
                                                      .Where(isAdult.Compile())
                                                      .Any())
                                         .ToList();
like image 200
StriplingWarrior Avatar answered Oct 17 '25 06:10

StriplingWarrior



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!