I just want to plug the referenced issue (#9539) that @smitpatel closed as duplicate of this.
It expands on the filter-by-tenant use case that is outlined in the ef core / what's new documentation.
Any chance this might make it for 2.1?
@pauldalyii Thanks for the feedback and the detailed example in #9539--this gives us good information on one concrete way people would use this. Unfortunately, I don't think this will fit in the 2.1 time frame.
@ajcvickers, thanks for letting me know. With some guidance, I'd be happy to try to implement this/get a rough PoC working. It seems like It'd be a cool feature.
@anpete Can you give @pauldalyii some guidance here?
One of the biggest blocker for this is nav expansion and filter application dependency. We expand navigations before applying filters so that we have entityQueryables for all the the ETs before applying filter (so that we can apply for all ETs appropriately). But having a navigation in filter means we need to expand navs after applying filter which can cause more filters to applied and that goes on (forever :trollface: ). We may need a way to integrate this inside nav expansion.
I just started tackling my EF-Core code's TODOs regarding filtering. I didn't get far before running up against the two limitations mentioned in What's New. My second use-case already needs both a navigation property and to be defined on a subclass Entity Type.
Limitations
- Navigation references are not allowed. This feature may be added based on feedback.
- Filters can only be defined on the root Entity Type of a hierarchy.
After further thought, I see how to work with both limitations in place.
At the top of every class hierarchy within my domain model, alongside ID, I'll add a persisted property like IsDeleted or perhaps the inverse IsActive that's a nullable boolean. As for the predicate that I was previously trying to pass to HasQueryFilter, I'll instead calculate it in memory and persist the result in this new property.
I can then use HasQueryFilter to filter on that property, rather than passing in the more complex predicate that comprises it. I'll do this concisely once for the entire model:
foreach ( var root in
from e in modelBuilder.Model.GetEntityTypes()
where e.BaseType == null
select e
) root.QueryFilter = (Expression<Func<IEntity, bool>>)(e => e.IsActive == null || e.IsActive.Value);
Does this look like a reasonable way to use the API? It does throw an exception, since the Func must accept a parameter with the root.ClrType instead of IEntity. Does EF-Core really need to enforce that? If not then please remove that check to make this scenario easier and more efficient. Otherwise, I'll have to dynamically build the lambda expression.
For my last TODO regarding filtering, I see _I do_ at least need navigation property support.
modelBuilder.Entity<Product>().HasQueryFilter( p =>
p.PurchasedBy.Any( o => o.ID == TenantID )
);
The work around I described above won't work here, since involved objects exist in the database but not local memory.
Please increase this issue's priority. 馃檹
did this ever get implemented?
@chumtoadafuq It shipped with EF Core 2.1.
Most helpful comment
For my last
TODOregarding filtering, I see _I do_ at least need navigation property support.The work around I described above won't work here, since involved objects exist in the database but not local memory.
Please increase this issue's priority. 馃檹