web-dev-qa-db-fra.com

Comment interroger une relation plusieurs-à-plusieurs dans EF Core

J'utilise .NET Core et EF Core pour un projet Web. Je n'arrive pas à interroger une relation plusieurs-à-plusieurs. Voici à quoi ressemblent mes modèles:

public class Begrip
{
    public int ID { get; set; }
    public string Name { get; set; } 
    public string Desc { get; set; }
    [Url]
    public string URL { get; set; } 
    public ICollection<BegripCategory> Categories { get; set; } 
}

public class Category
{
    public int ID { get; set; }
    public string Name { get; set; } 
    public ICollection<BegripCategory> Begrippen { get; set; }
}

public class BegripCategory
{
    public int begripId { get; set; }
    public Begrip begrip { get; set; } 
    public int categoryId { get; set; }
    public Category category { get; set; } 
}

Et mon contexte de base de données:

public class PBBContext : DbContext
{
    public PBBContext (DbContextOptions<PBBContext> options)
        : base(options)
    {
    }

    public DbSet<PBB.Models.Movie> Movie { get; set; }
    public DbSet<PBB.Models.Begrip> Begrip { get; set; } 
    public DbSet<PBB.Models.Category> Category { get; set; } 
    public DbSet<PBB.Models.BegripCategory> BegripCategory { get; set; }

    protected override void OnModelCreating(ModelBuilder modelbuilder)
    {
        modelbuilder.Entity<BegripCategory>().HasKey(bc => new { bc.begripId, bc.categoryId });

        modelbuilder.Entity<BegripCategory>().HasOne(b => b.begrip).WithMany(bg => bg.Categories).HasForeignKey(bc => bc.begripId);
        modelbuilder.Entity<BegripCategory>().HasOne(c => c.category).WithMany(ca => ca.Begrippen).HasForeignKey(cc => cc.categoryId);
    }
}

Ce que j'essaie de faire est de retourner tous les "Begrippen" dans un résultat JSON avec toutes les "Catégories" correspondantes, cependant, je ne peux pas comprendre comment obtenir la liste des "Catégories" pour eux.

Des idées? Merci d'avance.

14
JessengBijleng

EF Core ne chargera pas automatiquement les propriétés associées, vous devrez donc le faire explicitement, mais quelque chose comme ce qui suit devrait faire l'affaire:

var result = context.Begrip
    .Include(x => x.Categories)
    .ThenInclude(x => x.category);

Remarque, intellisense ne fonctionne pas toujours sur .ThenInclude pour le moment, mais le code devrait toujours être compilé même s'il est souligné en rouge.

Si vous renvoyez cela à la vue ou à une API, vous souhaiterez probablement le mapper à un DTO afin de ne pas avoir à gérer .Categories[0].category.Name etc.

17
Richard

Si vous devez filtrer une relation plusieurs-à-plusieurs décrite ci-dessous, je recommande d'utiliser une LinQ Enumerable Any méthode comme celle-ci:

return result.Where(x => x.Categories.Any(c => c.category == categoryId));

Pour renvoyer une liste filtrée d'entités liées par une catégorie spécifique.

exemple de requête de relation EntityFrameworkCore

5
GAzcuy

Étendre la réponse de @ Richard:

J'ai remarqué dans Visual Studio 2017 15.5.6 lorsque je fais ce qui suit:

            return _context.Begrip
            .Include(x => x.Categories)
                .ThenInclude(y => y.<nothing typed in here yet>)

IntelliSense me dit d'abord que y si de type ICollection de BegripCategory présentant des méthodes adaptées aux collections ce qui est déroutant surtout que lorsque je commence à taper "catégorie "(au lieu de" rien encore tapé ici ") IntelliSense change comme si nous ne faisions affaire qu'avec une seule instance au lieu de ICollection

Juste une petite remarque, mais j'espère que cela vous aidera à économiser quelques minutes de confusion.

1
GrayCat