Using EF Core HasQueryFilter on navigation properties

asp.net-core c# entity-framework-core

Question

I'm trying to apply a filter to my queries for multi-tenancy but it doesn't allow me to apply the filter when the property is part of a navigation property:

modelBuilder.Entity<Level>().HasQueryFilter(lvl => lvl.SchoolYear.TenantId == _tenantProvider.TenantId);

Here, Level is the property I want filtered but the property to use for filtering which is TenantId is is inside Level.SchoolYear.

If its a top-level property it works fine. How can I apply a global filter when the property I need for filtering is a navigation property?

1
4
11/25/2017 8:36:11 AM

Popular Answer

As said, these model level filters are not (yet) implemented for navigation properties. Which is sad, because people may not be aware of this restriction and count on it in a multi-tenant architecture. Everybody knows that making errors in a multi-tenant application may be the death of your company, so it's pretty vital to do this right.

Once you've chosen for tenant separation by TenantId (and not the safer schema-per-tenant or database-per-tenant), and knowing this current restriction in EF-core, you may want to build in a safeguard that at least you'll never mix up tenant data when saving changes.

This safeguard could be implemented by defining an interface:

public interface IHasTenantId
{
    int TenantId { get; }   
}

... to be implemented by each entity having a TenantId.

Then in an override of SaveChanges in the DbContext subclass there can be a check if all TenantIds in a change set are identical:

public override int SaveChanges()
{
    var distinctTenantIdsCount = this.ChangeTracker.Entries<IHasTenantId>()
                                     .Select(e => e.Entity.TenantId)
                                     .Distinct().Count();
    if(distinctTenantIdsCount > 1)
    {
        // Throw an exception and handle it.
    }
    return base.SaveChanges();
}
6
11/25/2017 11:18:08 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow