如何在 EF Core 中查询多对多关系

Posted

技术标签:

【中文标题】如何在 EF Core 中查询多对多关系【英文标题】:How to query many-to-many releationship in EF Core 【发布时间】:2017-11-13 23:07:24 【问题描述】:

我将 .NET Core 和 EF Core 用于 Web 项目。我正在努力如何查询多对多关系。这是我的模型的样子:

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;  

还有我的数据库上下文:

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);
    

我试图做的是在 JSON 结果中返回所有“Begrippen”以及所有相应的“类别”,但是,我不知道如何为它们获取“类别”列表。

有什么想法吗?提前致谢。

【问题讨论】:

【参考方案1】:

EF Core 不会自动加载相关属性,因此您需要显式执行此操作,但类似以下内容应该可以解决问题:

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

请注意,智能感知目前并不总是在 .ThenInclude 上工作,但即使代码出现红色下划线,它仍应编译。

如果您要将其返回到视图或 API,您可能希望将其映射到 DTO,这样您就不必处理 .Categories[0].category.Name 等。

【讨论】:

它叫Eager loading 在 EF Core 2.1 中使用无法编译的 VS 2017 15.9.7。 事实上,现在我看了你的回答,Begrip 没有Categories 属性,只有BegripCategory 属性。投反对票,请更新答案,我会投赞成票。 另外,很好奇如何在Select() 语句中迭代可变数量的BegripCategory 子实体。那可能吗?如果是这样,你能告诉我怎么做吗? 在这些条件下对我来说仍然编译得很好。 Begrip 确实有一个 Categories 属性,BegripCategory 属性在上下文中,而不是 Begrip 类。【参考方案2】:

如果您需要过滤下面描述的多对多关系,我建议使用 LinQ Enumerable Any 方法,如下所示:

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

返回与特定类别相关的经过过滤的实体列表。

EntityFrameworkCore Relationship query example

【讨论】:

【参考方案3】:

扩展@Richard 的回答:

当我执行以下操作时,我在 Visual Studio 2017 15.5.6 中注意到:

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

IntelliSense 起初告诉我 y if 的类型 ICollectionBegripCategory 呈现适合集合的方法 什么是令人困惑的,尤其是当我开始时输入“类别”(代替“这里没有输入任何内容”)IntelliSense 会发生变化,就好像我们只处理单个实例而不是 ICollection

只是一个小小的评论,但我希望它有助于节省几分钟的时间混乱。

【讨论】:

以上是关于如何在 EF Core 中查询多对多关系的主要内容,如果未能解决你的问题,请参考以下文章

如何在 .NET EF Core 中实现自引用多对多关系

EF Core中如何设置数据库表自己与自己的多对多关系

ef core中如何实现多对多的表映射关系

如何使用同一个连接表创建多个多对多关系 [EF7/Core]

如何直接填充由 EF Core 生成的多对多关系连接表?

EF Core 5,删除多对多关系