EF Core Globale Filter

EF Core Globale Filter

12. März 2024 | Gregor Koletzki | 2 Min. Lesezeit

Entity Framework Core (EF Core) ist ein leistungsstarkes ORM-Framework, das es Entwicklern ermöglicht, mit Datenbanken auf eine objektorientierte Weise zu interagieren. Eine der fortgeschrittenen Funktionen von EF Core ist das globale Filtern, das es ermöglicht, Abfragen so zu definieren, dass bestimmte Datensätze standardmäßig herausgefiltert werden.

Was ist globales Filtern?

Das globale Filtern in EF Core ermöglicht es Entwicklern, Filterbedingungen auf Entity-Typen anzuwenden, die dann automatisch auf alle Abfragen dieses Typs angewendet werden. Diese Filterbedingungen werden auf Datenbankebene angewendet, was bedeutet, dass sie unabhängig davon gelten, wie die Daten in der Anwendung abgerufen werden.

Warum globales Filtern verwenden?

Datensicherheit: Durch das globale Filtern können sensible Daten automatisch ausgeblendet werden, sodass nur autorisierte Benutzer darauf zugreifen können.
Konsistenz: Das globale Filtern gewährleistet eine konsistente Datenansicht, da die Filterbedingungen standardmäßig auf alle Abfragen angewendet werden.
Codevereinfachung: Entwickler müssen nicht jedes Mal manuell Filterbedingungen hinzufügen, wenn sie auf bestimmte Daten zugreifen möchten. Das globale Filtern übernimmt diese Aufgabe automatisch.

Wie implementiert man globales Filtern in EF Core?

Um globales Filtern in EF Core zu implementieren, folgen Sie diesen Schritten:

Definieren Sie den Filter: Verwenden Sie die HasQueryFilter-Methode in der OnModelCreating-Methode Ihres DbContext, um das globale Filter zu definieren. Hier ist ein Beispiel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<YourEntity>()
        .HasQueryFilter(e => !e.IsDeleted);
}

Anwenden des Filters: Das globale Filter wird nun auf alle Abfragen angewendet, die diesen Entity-Typ betreffen. In diesem Beispiel werden alle gelöschten Einträge ausgeblendet.

Beispielanwendung: Soft Deletes

Ein häufiges Anwendungsbeispiel für globales Filtern ist die Implementierung von Soft Deletes. Indem Sie ein globales Filter definieren, das gelöschte Einträge ausblendet, können Sie Soft Deletes einfach implementieren, ohne jedes Mal manuell nach nicht gelöschten Einträgen filtern zu müssen.

Globalen Filter dynamisch setzen.

In Szenarien die Daten Benutzerabhängig oder Tenant abhängig zurück geben, muss man den Filter mit dynamischen Daten setzen. Dies ist in EF Core auch möglich. In diesem Beispiel zeige ich euch wie man Daten Benutzerabhängig von der Datenbank filtert.

Erstelle eine Klasse die den Benutzer abbildet für den die Daten gefiltert werden sollen. Es kann der Angemeldete Benutzer am System sein:

public class DbCurrentUser
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public DbCurrentUser(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public string? UserId => _httpContextAccessor.HttpContext?
        .User
        .FindFirst(ClaimTypes.NameIdentifier)?.Value;
}

Als nächstes können wir unser DbContext so erweitern, dass in der Methode OnModelCreating wir alle Entitäten zusammen suchen die von einem Interface ICurrentUserEntity ableiten. An diesen Entitäten registrieren wir den Filter, den wir als LambdaExpression uns zusammen bauen, mit der Methode HasQueryFilter.

public class CustomDbContext : DbContext
{
    private readonly DbCurrentUser _dbCurrentUser;
    private string? UserId => _dbCurrentUser.UserId;
    
    public CustomDbContext(
        DbContextOptions<CustomDbContext> options, 
        DbCurrentUser dbCurrentUser)
        :base(options)
    {
        _dbCurrentUser = dbCurrentUser;
    }
    
    protected override void OnModelCreating(ModelBuilder modelBuilder) 
    { 
        base.OnModelCreating(modelBuilder); 
        modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); 
        var currentUserEntities = typeof(ICurrentUserEntity).Assembly.GetTypes() 
            .Where(type => typeof(ICurrentUserEntity) .IsAssignableFrom(type) && type.IsClass); 
 
        foreach (var currentUserEntity in currentUserEntities) 
        { 
            modelBuilder.Entity(currentUserEntity).HasQueryFilter(GenerateQueryFilterLambdaExpression(currentUserEntity)); 
        } 
    } 
    
    private LambdaExpression GenerateQueryFilterLambdaExpression(Type type) 
    { 
        // x => 
        var parameter = Expression.Parameter(type, "x"); 
 
        // x.UserId 
        Expression entityUserId = Expression.Property(parameter, nameof(ICurrentUserEntity.UserId)); 
 
        // this 
        var dbContextConstant = Expression.Constant(this, GetType()); 
 
        // this.UserId 
        var dbContextUserId = Expression.Property(dbContextConstant, nameof(UserId)); 
 
        // x.UserId == this.UserId 
        var userCheck = Expression.Equal(entityUserId, dbContextUserId); 
        return Expression.Lambda(userCheck , parameter); 
    } 
}

In diesem Beispiel werden alle Abfragen auf den Entitäten die ICurrentUserEntity implementieren so gefiltert, dass nur Datensätze abgefragt werden die dem Benutzer gehören.

Fazit

Das globale Filtern in EF Core ist eine leistungsstarke Funktion, die Entwicklern ermöglicht, Filterbedingungen auf Entity-Typen anzuwenden, die standardmäßig auf alle Abfragen angewendet werden. Durch die Implementierung von globalem Filtern können Sie die Datensicherheit verbessern, die Konsistenz gewährleisten und den Code vereinfachen.`

Kategorien

Kontaktieren Sie uns:

Harksheider Weg 60H,
25451 Quickborn
+49 1520 40 73 253
info@gk-itsolutions.de

Schnellzugriff:

Folgt uns auf: