如何在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
相关产品推荐
相关产品推荐

