Types de requêtesQuery Types

Note

Cette fonctionnalité est une nouveauté dans EF Core 2.1This feature is new in EF Core 2.1

En plus des types d’entité peut contenir un modèle EF Core types de requête, qui peut être utilisé pour effectuer des requêtes de base de données sur des données qui n’est pas mappées aux types d’entités.In addition to entity types, an EF Core model can contain query types, which can be used to carry out database queries against data that isn't mapped to entity types.

Types de requêtes présentent de nombreuses similitudes avec les types d’entités :Query types have many similarities with entity types:

  • Ils peuvent également être ajoutés au modèle soit dans OnModelCreating, ou via une propriété « set » sur une dérivée DbContext.They can also be added to the model either in OnModelCreating, or via a "set" property on a derived DbContext.
  • Ils prennent en charge plusieurs capacités de mappage même, comme l’héritage de mappage, les propriétés de navigation (voir limitations ci-dessous), puis, dans des magasins relationnels, la possibilité de configurer les objets de base de données cible et les colonnes via les méthodes de l’API fluent ou de l’annotation de données.They support many of the same mapping capabilities, like inheritance mapping, navigation properties (see limitations below) and, on relational stores, the ability to configure the target database objects and columns via fluent API methods or data annotations.

Toutefois ils sont différents d’entité types dans ce qu’il :However they are different from entity types in that they:

  • Ne nécessitent pas une clé à définir.Do not require a key to be defined.
  • Ne sont jamais suivies pour les modifications sur le DbContext et par conséquent sont jamais insérées, mises à jour ou de suppression sur la base de données.Are never tracked for changes on the DbContext and therefore are never inserted, updated or deleted on the database.
  • Ne sont jamais détectés par convention.Are never discovered by convention.
  • Prennent uniquement en charge un sous-ensemble des fonctionnalités de mappage de navigation - plus précisément :Only support a subset of navigation mapping capabilities - Specifically:
    • Ils ne peuvent jamais agir en tant que l’extrémité principale d’une relation.They may never act as the principal end of a relationship.
    • Ils ne peuvent contenir que des propriétés de navigation de référence en pointant sur les entités.They can only contain reference navigation properties pointing to entities.
    • Entités ne peut pas contenir de propriétés de navigation pour les types de requêtes.Entities cannot contain navigation properties to query types.
  • Sont traitées sur le ModelBuilder à l’aide de la Query méthode plutôt que la Entity (méthode).Are addressed on the ModelBuilder using the Query method rather than the Entity method.
  • Sont mappées sur le DbContext via les propriétés de type DbQuery<T> au lieu de DbSet<T>Are mapped on the DbContext through properties of type DbQuery<T> rather than DbSet<T>
  • Sont mappées à des objets de base de données à l’aide de la ToView méthode, plutôt que ToTable.Are mapped to database objects using the ToView method, rather than ToTable.
  • Peut être mappé à un définition de requête - une définition de requête est une requête secondaire déclarée dans le modèle qui fait Office de source de données pour un type de requête.May be mapped to a defining query - A defining query is a secondary query declared in the model that acts a data source for a query type.

Parmi les principaux scénarios d’utilisation pour les types de requêtes, citons :Some of the main usage scenarios for query types are:

  • Agissant en tant que type de retour pour ad hoc FromSql() requêtes.Serving as the return type for ad hoc FromSql() queries.
  • Mappage de vues de base de données.Mapping to database views.
  • Mappage des tables qui n’ont pas de clé primaire définie.Mapping to tables that do not have a primary key defined.
  • Mappage pour les requêtes définies dans le modèle.Mapping to queries defined in the model.

Conseil

Mappage d’un type de requête à un objet de base de données est obtenue grâce à la ToView API fluent.Mapping a query type to a database object is achieved using the ToView fluent API. Du point de vue du noyau de EF, l’objet de base de données spécifiée dans cette méthode est un vue, c'est-à-dire qu’il est traité comme une source de la requête en lecture seule et ne peut pas être la cible d’une mise à jour, insérer ou supprimer les opérations.From the perspective of EF Core, the database object specified in this method is a view, meaning that it is treated as a read-only query source and cannot be the target of update, insert or delete operations. Toutefois, cela ne signifie pas que l’objet de base de données est réellement nécessaire pour la vue de base de données, il peut également être une table de base de données qui sera traitée comme étant en lecture seule.However, this does not mean that the database object is actually required to be a database view - It can alternatively be a database table that will be treated as read-only. À l’inverse, pour les types d’entité, EF Core suppose qu’un objet de base de données spécifié dans le ToTable méthode peut être traitée comme un table, ce qui signifie qu’il peut être utilisé en tant que requête source, mais également ciblés par la mise à jour, supprimer et insérer opérations.Conversely, for entity types, EF Core assumes that a database object specified in the ToTable method can be treated as a table, meaning that it can be used as a query source but also targeted by update, delete and insert operations. En fait, vous pouvez spécifier le nom d’une vue de base de données dans ToTable et tout devrait fonctionner correctement tant que la vue est configurée pour être mis à jour sur la base de données.In fact, you can specify the name of a database view in ToTable and everything should work fine as long as the view is configured to be updatable on the database.

ExempleExample

L’exemple suivant montre comment utiliser le Type de requête pour interroger une vue de base de données.The following example shows how to use Query Type to query a database view.

Conseil

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

Tout d’abord, nous définissons un modèle simple de Blog et Post :First, we define a simple Blog and Post model:

public class Blog
{
    public int BlogId { get; set; }
    public string Name { get; set; }
    public string Url { get; set; }
    public ICollection<Post> Posts { get; set; }
}

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

Ensuite, nous définissons une vue de base de données simple qui permet d’interroger le nombre de messages associée à chaque blog :Next, we define a simple database view that will allow us to query the number of posts associated with each blog:

db.Database.ExecuteSqlCommand(
    @"CREATE VIEW View_BlogPostCounts AS 
        SELECT Name, Count(p.PostId) as PostCount from Blogs b
        JOIN Posts p on p.BlogId = b.BlogId
        GROUP BY b.Name");

Ensuite, nous définissons une classe pour contenir le résultat de la vue de base de données :Next, we define a class to hold the result from the database view:

public class BlogPostsCount
{
    public string BlogName { get; set; }
    public int PostCount { get; set; }
}

Ensuite, nous configurons le type de requête dans OnModelCreating à l’aide de la modelBuilder.Query<T> API.Next, we configure the query type in OnModelCreating using the modelBuilder.Query<T> API. API de configuration fluent standard nous permet de configurer le mappage pour le Type de requête :We use standard fluent configuration APIs to configure the mapping for the Query Type:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Query<BlogPostsCount>().ToView("View_BlogPostCounts")
        .Property(v => v.BlogName).HasColumnName("Name");
}

Enfin, nous pouvons interrogez la vue de base de données de la façon standard :Finally, we can query the database view in the standard way:

var postCounts = db.BlogPostCounts.ToList();

foreach (var postCount in postCounts)
{
    Console.WriteLine($"{postCount.BlogName} has {postCount.PostCount} posts.");
    Console.WriteLine();
}

Conseil

Notez que nous avons également de définir une propriété de niveau de requête (DbQuery) d’agir en tant que racine pour les requêtes sur ce type de contexte.Note we have also defined a context level query property (DbQuery) to act as a root for queries against this type.