EntityFramework.DynamicFilters
EntityFramework.DynamicFilters copied to clipboard
TPH Inheritance and filtering problem
I have this inheritance:
public abstract class FeatureSetting
{
public int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Value { get; set; }
}
public class EditionFeatureSetting : FeatureSetting
{
public virtual int EditionId { get; set; }
}
public class TenantFeatureSetting : FeatureSetting, IMustHaveTenant
{
public virtual int TenantId { get; set; }
}
My filtering interface is IMustHaveTenant. I defined filter as shown below:
modelBuilder.Filter(AbpDataFilters.MustHaveTenant, (IMustHaveTenant t, int tenantId) => t.TenantId == tenantId, 0);
All is good. But, when I query EditionFeatureSettings from database, it adds TenantId filter to the query, and thus I can not get any EditionFeatureSettings. Actually, filtering should be only applied for TenantFeatureSetting, since only it defines TenantId. So, when I query EditionFeatureSettings, it should not apply any filtering, but it does.
Thanks a lot.
So it's adding a filter against the "TenantId" column on the EditionFeatureSession table? Is that generating a SQL error then since the column TenantId does not exist in table EditionFeatureSession?
I have never seen a filter wrongly applied to an entity before...
Oh, this is TPH. That means both entities are in the same table.
And also I saw it in unit tests, not tested against SQL Server to see generated SQL. I can also do it if this is not enough. Thanks a lot.
I'll take a look at this in more detail. But at first glance, this is going to be a difficult situation to handle - if it's possible at all.
That filter would need to know to automatically include a condition that matches on a discriminator value. And the only immediate information I have to go on is "IMustHaveTenant" which obviously has no knowledge of the entity being TPH, let alone the column name of the discriminator and what value should be used.
At this point (5 minutes of research), I don't know if EF exposes enough information for me to figure this out. Especially to the level of determining the discriminator values that would be needed.
2 possible workarounds that come to mind:
- If you have re-mapped the discriminator column to specific values in your entities, you can change your filter to include a condition on those values (see "Change Discriminator Column here for what I am talking about: http://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table-per-hierarchy-tph).
- Or if you let TenantId default to 0 for your FeatureSetting entities and it's always > 0 for TenantFeatureSetting, you can change your filter to "(t.TenantId == 0) || (t.TenantId == tenantId)".
I'll see if I can come up with a better solution but it may take some time.
Thank you for your comments. I'll try workarounds and write here again.
Hi again,
I changed my filter definition like that:
modelBuilder.Filter(AbpDataFilters.MustHaveTenant, (IMustHaveTenant t, int tenantId) => t.TenantId == tenantId || (int?)t.TenantId == null, 0);
and it worked! It seems strange to cast int to int? but it's null for EditionFeatureSetting entities, and it works.
Thank you much for leading me to the right direction.
Glad to hear you found a solution. I'll keep this issue open until I have a chance to look at it closer. Maybe I can come up with a cleaner solution.
Changed my filter definition like that gives no warning at all:
modelBuilder.Filter(AbpDataFilters.MustHaveTenant, (IMustHaveTenant t, int tenantId) => t.TenantId == tenantId || (t.TenantId as int?) == null, 0);