You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在EF Core中不使用JOIN语句通过外键获取关联评论

问题描述

我定义了两个实体类:

public class Post
{
    public long Id { get; set; } = default!;
    public string Description { get; set; } = default!;
    public IEnumerable<Comment>? Comments { get; set; } = default!;
}

public class Comment
{
    public int Id { get; set; } = default!;
    public string Content { get; set; } = default!;
    public Post Post { get; set; } = default!;
}

我将这两个类都添加到DbContext中,并按如下方式初始化数据:

Comment[] comments = new Comment[30];

for (int i = 0; i < comments.Length; i++)
{
    comments[i] = new() { Content = $"Comment {i}" };
}

context.Posts.AddRange(
    new() { Description = "Description1", Comments = comments },
    new() { Description = "Description2" },
    new() { Description = "Description3" }
);

context.SaveChanges();

在后续业务逻辑中,我需要获取属于指定ID帖子的所有评论(无需获取帖子本身),但尝试以下两种写法时,EF Core都会生成不必要的JOIN语句:

写法1:

var a = await _dbContext.Comments
                        .Where(c => c.Post.Id == id)
                        .ToListAsync();

写法2:

var a = await _dbContext.Comments
                        .Where(c => c.Post == new Post() { Id = id} )
                        .ToListAsync();

请问有没有合适的实现方式可以避免生成JOIN?


解决方案

问题根源在于Comment实体类没有显式定义外键属性,EF Core只能通过导航属性Post关联查询,因此会生成JOIN语句。推荐两种解决方式:

方式1:给Comment类添加显式外键属性

直接在Comment类中添加对应Post的外键字段,这是最直观的方案:

public class Comment
{
    public int Id { get; set; } = default!;
    public string Content { get; set; } = default!;
    // 添加Post的外键属性
    public long PostId { get; set; } = default!;
    public Post Post { get; set; } = default!;
}

之后直接通过外键字段查询,EF Core会生成不含JOIN的SQL:

var comments = await _dbContext.Comments
                               .Where(c => c.PostId == id)
                               .ToListAsync();

方式2:通过模型配置指定外键(无需修改实体类)

如果不想修改实体类,可以在DbContext的OnModelCreating方法中显式配置外键关系:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Comment>()
        .HasOne(c => c.Post)
        .WithMany(p => p.Comments)
        .HasForeignKey("PostId"); // 指定数据库中的外键列名
}

查询时通过EF Core的Property方法访问外键列:

var comments = await _dbContext.Comments
                               .Where(c => EF.Property<long>(c, "PostId") == id)
                               .ToListAsync();

这种写法不如添加实体属性直观,仅推荐在无法修改实体类的场景下使用。

内容的提问来源于stack exchange,提问作者A.Ston

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 13:41:48