Voglio aggiungere il filtro globale per la riga eliminata dal framework di entità. E ottengo questo da questo codice nella classe DbContext.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Role>().HasQueryFilter(p => !p.IsDeleted);
modelBuilder.Entity<User>().HasQueryFilter(p => !p.IsDeleted);
modelBuilder.Entity<Foo>().HasQueryFilter(p => !p.IsDeleted);
modelBuilder.Entity<Bar>().HasQueryFilter(p => !p.IsDeleted);
.
.
.
}
Ma per ogni tabella, aggiungo una nuova riga al metodo OnModelCreating. Come posso farlo con una riga per ogni tabella come questa?
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<T>().HasQueryFilter(p => !p.IsDeleted);
}
Non è possibile testare l'API esatta, ma l'approccio generale sarebbe quello di creare un metodo generico vincolato e chiamarlo tramite riflessione:
public static class EFFilterExtensions
{
public static void SetSoftDeleteFilter(this ModelBuilder modelBuilder, Type entityType)
{
SetSoftDeleteFilterMethod.MakeGenericMethod(entityType)
.Invoke(null, new object[] { modelBuilder });
}
static readonly MethodInfo SetSoftDeleteFilterMethod = typeof(EFFilterExtensions)
.GetMethods(BindingFlags.Public | BindingFlags.Static)
.Single(t => t.IsGenericMethod && t.Name == "SetSoftDeleteFilter");
public static void SetSoftDeleteFilter<TEntity>(this ModelBuilder modelBuilder)
where TEntity : class, ISoftDeleteModel
{
modelBuilder.Entity<TEntity>().HasQueryFilter(x => !x.IsDeleted);
}
}
Ora puoi usare qualcosa di simile all'interno di OnModelCreating
:
foreach (var type in modelBuilder.Model.GetEntityTypes())
{
if (typeof(ISoftDeleteModel).IsAssignableFrom(type.ClrType))
modelBuilder.SetSoftDeleteFilter(type.ClrType);
}
Nel caso in cui si abbia una classe base o un'interfaccia che definisce la proprietà IsActive
, è possibile utilizzare l'approccio Filtra tutte le query (cercando di ottenere l'eliminazione graduale ) .
Altrimenti potresti iterare i tipi di entità, e per ogni tipo con bool IsActive
proprietà bool IsActive
in modo dinamico il filtro dell'espressione usando i metodi della classe Expression
:
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
var isActiveProperty = entityType.FindProperty("IsActive");
if (isActiveProperty != null && isActiveProperty.ClrType == typeof(bool))
{
var parameter = Expression.Parameter(entityType.ClrType, "p");
var filter = Expression.Lambda(Expression.Property(parameter, isActiveProperty.PropertyInfo), parameter);
entityType.QueryFilter = filter;
}
}
Aggiornamento (EF Core 3.0): a causa della modifica della rottura dell'API dei metadati pubblici (sostituzione di molte proprietà con i metodi di estensione Get
/ Set
), l'ultima riga diventa
entityType.SetQueryFilter(filter);