I am trying to change the way asp.net generates its identity tables, trying to base the generation on an Id of int instead of a Guid(string), also adding a different schema(instead of dbo -> Security) and a QueryFilter for all my entities, in that case I created for each class a Mapping but will illustrate the idea with just one that is giving me the error.
public class AspNetRole : IdentityRole<int>, IEntityBase
{
public bool IsDeleted { get; set; }
public string CreatedBy { get; set; }
public string UpdatedBy { get; set; }
public DateTime? CreatedOn { get; set; }
public DateTime? UpdatedOn { get; set; }
}
public interface IEntityBase
{
int Id { get; set; }
bool IsDeleted { get; set; }
string CreatedBy { get; set; }
string UpdatedBy { get; set; }
DateTime? CreatedOn { get; set; }
DateTime? UpdatedOn { get; set; }
}
The mapping class with the QueryFilter:
public class AspNetRoleMap : IEntityTypeConfiguration<AspNetRole>
{
public void Configure(EntityTypeBuilder<AspNetRole> builder)
{
builder.ToTable(name: "AspNetRole", schema: "Security");
builder.HasQueryFilter(app => !app.IsDeleted);
}
}
The DbContext:
public class AspNetSecurityDbContext : IdentityDbContext<AspNetUser, IdentityRole<int>, int>
{
public AspNetSecurityDbContext(DbContextOptions<AspNetSecurityDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ApplyConfiguration(new AspNetRoleMap());
}
}
Once I run the migration I am getting the following error:
The filter expression 'app => Not(app.IsDeleted)' cannot be specified for entity type 'AspNetRole'. A filter may only be applied to the root entity type in a hierarchy.
I tried this approach https://github.com/aspnet/EntityFrameworkCore/issues/10259 but still getting more errors
builder.HasQueryFilter(app => !((IEntityBase)app).IsDeleted);
The problem has nothing in common with EF Core query filter, but the incorrect base generic IdentityDbContext
argument. Here
: IdentityDbContext<AspNetUser, IdentityRole<int>, int>
you are passing IdentityRole<int>
, which in the base OnModelCreating
will be configured as entity, hence EF Core will map your AspNetRole
entity using TPH inheritance strategy, which along with the additional discriminator column introduces additional constraints, like the query filter exception you are getting.
To fix that, pass the correct generic type argument which in this case is the custom AspNetRole
class:
: IdentityDbContext<AspNetUser, AspNetRole, int>
In case you create other custom entities inheriting the generic IndentityXyz<>
classes, take a look at the other base IdentityDbContext
classes having more generic type arguments, and select the one that allows you the pass all your custom identity derived types.