Filtres de requête globaleGlobal Query Filters

Les filtres de requête globale permet aux prédicats de requête LINQ (expression booléenne généralement passée à l’opérateur de requête LINQ Where) d’être appliqués sur des types d’entité dans le modèle de métadonnées (généralement dans OnModelCreating).Global query filters are LINQ query predicates (a boolean expression typically passed to the LINQ Where query operator) applied to Entity Types in the metadata model (usually in OnModelCreating). Ces filtres sont automatiquement appliqués à toutes les requêtes LINQ impliquant ces types d’entités, y compris ceux référencés indirectement, par exemple à l’aide d’Include ou de références de propriété de navigation directe.Such filters are automatically applied to any LINQ queries involving those Entity Types, including Entity Types referenced indirectly, such as through the use of Include or direct navigation property references. Voici deux applications courantes de cette fonctionnalité :Some common applications of this feature are:

  • Suppression réversible : un type d’entité définit une propriété IsDeleted.Soft delete - An Entity Type defines an IsDeleted property.
  • Architecture multilocataire : un type d’entité définit une propriété TenantId.Multi-tenancy - An Entity Type defines a TenantId property.

ExempleExample

L’exemple suivant montre comment utiliser les filtres de requête globale pour implémenter des comportements de suppression réversible et d’architecture multilocataire dans un modèle de création de blogs simple.The following example shows how to use Global Query Filters to implement soft-delete and multi-tenancy query behaviors in a simple blogging model.

Conseil

Vous pouvez afficher cet exemple sur GitHub.You can view this article's sample on GitHub.

Tout d’abord définissez les entités :First, define the entities:

public class Blog
{
    private string _tenantId;

    public int BlogId { get; set; }
    public string Name { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public bool IsDeleted { get; set; }

    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}

Notez la déclaration d’un champ _tenantId sur l’entité Blog.Note the declaration of a _tenantId field on the Blog entity. Celui-ci doit servir à associer chaque instance de blog à un client spécifique.This will be used to associate each Blog instance with a specific tenant. Une propriété IsDeleted est également définie sur le type d’entité Post.Also defined is an IsDeleted property on the Post entity type. Elle est utilisée pour déterminer si une instance Post a été « supprimée de façon réversible ».This is used to keep track of whether a Post instance has been "soft-deleted". Autrement dit, l’instance est marquée comme supprimée sans que les données sous-jacentes soient réellement supprimées.That is, the instance is marked as deleted without physically removing the underlying data.

Ensuite, configurez les filtres de requête dans OnModelCreating à l’aide de l’API HasQueryFilter.Next, configure the query filters in OnModelCreating using the HasQueryFilter API.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>().Property<string>("TenantId").HasField("_tenantId");

    // Configure entity filters
    modelBuilder.Entity<Blog>().HasQueryFilter(b => EF.Property<string>(b, "TenantId") == _tenantId);
    modelBuilder.Entity<Post>().HasQueryFilter(p => !p.IsDeleted);
}

Les expressions de prédicat passées aux appels HasQueryFilter seront désormais automatiquement appliquées à toutes les requêtes LINQ pour ces types.The predicate expressions passed to the HasQueryFilter calls will now automatically be applied to any LINQ queries for those types.

Conseil

Notez l’utilisation d’un champ de niveau d’instance DbContext : _tenantId permet de définir le client en cours.Note the use of a DbContext instance level field: _tenantId used to set the current tenant. Les filtres au niveau du modèle utilisent la valeur de l’instance de contexte correcte (c’est-à-dire celle qui exécute la requête).Model-level filters will use the value from the correct context instance (that is, the instance that is executing the query).

Désactivation des filtresDisabling Filters

Les filtres peuvent être désactivés pour des requêtes LINQ individuelles à l’aide de l’opérateur IgnoreQueryFilters().Filters may be disabled for individual LINQ queries by using the IgnoreQueryFilters() operator.

blogs = db.Blogs
    .Include(b => b.Posts)
    .IgnoreQueryFilters()
    .ToList();

LimitationsLimitations

Les filtres de requête globale présentent les limitations suivantes :Global query filters have the following limitations:

  • Les filtres ne peuvent pas contenir de références à des propriétés de navigation.Filters cannot contain references to navigation properties.
  • Les filtres ne peuvent être définis que pour le type d’entité racine d’une hiérarchie d’héritage.Filters can only be defined for the root Entity Type of an inheritance hierarchy.