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?
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();
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With