When we use entity framework to manipulate SQL database, we use
where
to query and include
to load related
entities (join operation).
Sample database table schema: Employee: Id, Name, Age Salary: Id,
BasePay
Typical query scenarios:
- Query employee 3's name => Employee.Where(x => x.Id == 3)
- Query employee Jack's age => Employee.Where(x => x.Name ==
"Jack")
- Query employee Jack's basepay => Employee.Where(x => x.Name ==
"Jack").Include(x => x.Salary) ...
To make the code clean and focus, the following examples will not
include dbContext creation logic, we assume
db = DbContext()
which contains the Employee table.
For code reuse purpose, we may extract a common method like this:
Employee GetEntity(Func<Employee, bool> whereFunc, Func<DbSet<Employee>, IQueryable<Employee>> navigationFunc = null)
{
IQueryable<Employee> query = navigationFunc != null ? navigationFunc(db.Employee) : db.Employee;
var employee = await query.Where(x => whereFunc(x)).ToListAsync();
return employee;
}
The implmentation looks simple and straightfoward: just extract the
where and navigation Func<>
to a function.
However, the above function has severe perfomance issue: when we
execute the function, it retrieves all data from the table and locally
applies where
filter. Actually, the underlying mechanism is
not that simple as entity framework will compile the expression and
translated to SQL statements, though it looks like just a syntactic
sugar.