Entity Framework Lambda predicate stored in var wi

2019-09-21 23:09发布

问题:

I have a generic repository using EF6. The issue has to do with association properties requiring an "Include" even though it shouldn't. The following works:

IQueryable<User> dbQuery = _db.Set<User>();
return dbQuery.Where(x => x.Child.Name == "Foo").ToList();

However, the following does not work:

Func<User, bool> filter = x => x.Child.Name == "Foo";
IQueryable<User> dbQuery = _db.Set<User>();
return dbQuery.Where(filter).ToList();

It throws an "Object Reference not set..." exception on Child.

The following resolves it:

Func<User, bool> filter = x => x.Child.Name == "Foo";
IQueryable<User> dbQuery = _db.Set<User>();
dbQuery = dbQuery.Include(x => x.Child);
return dbQuery.Where(filter).ToList();

I don't understand why this is necessary though. Anyone know a way to resolve this without using the "Include"?

回答1:

You are should use Expression to let EF provider parse your query.

Change the Func<User, bool> to Expression<Func<User, bool>>



回答2:

The first snippet is providing an Expression to Where, which is being translated into SQL, and is doing the entire operation in the database. The latter two are passing a compiled method to Where, which it can't translate into SQL, which means that the entire database table is being pulled down into memory, and the entire operation is run in your application. When you pull down the whole table it doesn't pull down related records unless you Include them.

The solution is not to pull down both the entire table and also all of the data from all of the related records; the solution is to do the filtering in the database rather than in your application.