According to the docs we have the possibility to use Where()
inside Include
in EF Core 5. So this code is working well:
var groups = dbContext.DocumentGroups .Include(e => e.Types.Where(x => true)) .OrderBy(e => e.Name);
Now I have to refactor my filter (in this case simplified) – so I tried an extension method like this:
public static IEnumerable<T> MyFilter<T>(this IEnumerable<T> query) { // ... do a lot of filter stuff here return query.Where(e => true); }
and call it like this:
var groups = dbContext.DocumentGroups .Include(e => e.Types.MyFilter()) .OrderBy(e => e.Name);
I get an exception:
The expression ‘e.Types.MyFilter(__dbContext_1)’ is invalid inside an ‘Include’ operation, since it does not represent a property access: ‘t => t.MyProperty’. To target navigations declared on derived types, use casting (‘t => ((Derived)t).MyProperty’) or the ‘as’ operator (‘t => (t as Derived).MyProperty’). Collection navigation access can be filtered by composing Where, OrderBy(Descending), ThenBy(Descending), Skip or Take operations. For more information on including related data, see http://go.microsoft.com/fwlink/?LinkID=746393.
How can I fix this?
Answer
I think the main thing here is that you need to provide an Expression
to your include. If you want to refactor and have it as a testable, reusable independent unit you can create for example a static Expression property that you then can pass to the Include
method.
Something like;
public static Expression<Func<MyStoreObject, IEnumerable<MySubType>>> MyIncludeExpression { get { return e => e.Types.Where(x => true); } }
(MyStoreObject
being the type of the DocumentGroups, MySubType
being the type of the property Types
enumerable.)
and call it with
var groups = dbContext.DocumentGroups .Include(MyClass.MyIncludeExpression) .OrderBy(e => e.Name);
See the documentation of the EntityFrameworkQueryableExtensions.Include Method.