Search code examples
c#linqentity-framework-corefunc

Entity Framework Core: Passing a function to a Where and doing a Select will construct the object?


I am running into a very confusing issue with querying data in EF Core, and hoping that I can find the answer here.

I have School and Student entities that are mapped to the tables with the same name in database. There is a one to many association between them(School has many students).

When I do:

Func<Student, bool> whereClause = s => s.School!=null; 
var studentNames = efContext.Students.Where(whereClause).Select(s=>s.Name).ToList();

It is trying to instantiate the Student class, where I am only doing a select for name. But when I do the following:

var studentNames = efContext.Students.Where(s => s.School!=null).Select(s=>s.Name).ToList();

It doesn't create a new instance of the Student class.

What is the difference here?

My expectation is that, in either case instance of the Student class shouldn't be created.


Solution

  • I believe you need to wrap the Func in an Expression in order for Entity Framework to work its magic. So

    Expression<Func<Student, bool>> whereClause = s => s.School != null;
    

    Also, assuming Student has a foreign key, SchoolId, to a School, you will probably get better results from

    Expression<Func<Student, bool>> whereClause = s => s.SchoolId != null;
    

    The latter expression translates to SQL relatively easily — not sure how "is the navigation property null" from the former expression translates (which might be why it's instantiating the School object — you're no longer in "SQL mode").

    Possibly helpful: What's the purpose of the Expression class?