EF Core使用Include关联查询时如何排除指定大字段列避免冗余数据加载
优化方案
你可以通过以下几种方式实现需求,避免加载大体积的Content字段:
方案1:使用投影查询(最推荐)
直接通过Select自定义查询返回的字段,不需要使用Include,EF会自动生成只查询所需字段的SQL语句,性能最优。
如果可以接受匿名类型返回,代码如下:
var teachingProgrammeResult = await _context.TeachingProgrammes .Where(x => x.Id == request.TeachingProgrammeId) .Select(tp => new { tp.Id, tp.Name, TeachingProgrammeFiles = tp.TeachingProgrammeFiles .Select(f => new { f.Id, f.Name }) .ToList() }) .FirstOrDefaultAsync();
如果需要强类型返回,你可以定义对应的DTO类再做投影,示例:
// 定义DTO public class TeachingProgrammeDto { public int Id { get; set; } public string Name { get; set; } public List<TeachingProgrammeFileDto> TeachingProgrammeFiles { get; set; } } public class TeachingProgrammeFileDto { public int Id { get; set; } public string Name { get; set; } } // 查询代码 var teachingProgrammeResult = await _context.TeachingProgrammes .Where(x => x.Id == request.TeachingProgrammeId) .Select(tp => new TeachingProgrammeDto { Id = tp.Id, Name = tp.Name, TeachingProgrammeFiles = tp.TeachingProgrammeFiles .Select(f => new TeachingProgrammeFileDto { Id = f.Id, Name = f.Name }) .ToList() }) .FirstOrDefaultAsync();
方案2:配置大字段为延迟加载
如果你必须返回原始的TeachingProgramme实体类型,可以将Content属性配置为延迟加载,只有主动访问该属性时才会触发查询:
- 首先修改
TeachingProgrammeFile实体,给Content属性加virtual修饰符:
public virtual byte[] Content { get; set; }
- 开启EF Core的延迟加载功能,在DbContext的
OnConfiguring方法中添加配置:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseLazyLoadingProxies(); // 其余配置保持不变 }
注意:该方案需要保证访问实体属性时DbContext未被释放,否则会触发异常。
方案3:表拆分配置
如果绝大多数场景都不需要查询Content字段,可以将大字段拆分到单独的表中,平时查询主表时不会加载大字段,需要时再单独查询:
在DbContext的OnModelCreating方法中添加配置:
modelBuilder.Entity<TeachingProgrammeFile>() .SplitToTable("TeachingProgrammeFileContents", builder => { builder.Property(f => f.Content).HasColumnName("Content"); builder.HasOne(f => f.TeachingProgramme).WithMany(); });
内容的提问来源于stack exchange,提问作者ervin
相关产品推荐
相关产品推荐

