EF一对一关系下如何通过Include过滤关联数据?
解决方案
1. 直接用Filtered Include过滤一对一关联
EF Core的Filtered Include支持一对一(引用类型)导航属性,只是文档未单独说明。你可以在Include后链式调用Where过滤关联的Upload,不满足条件时该导航属性会自动返回null:
public async Task<Challenge?> GetByIdAsync(int id) { var item = await _context.Challenges .Include(x => x.Upload) .Where(u => u.DeletedOn == null) .FirstOrDefaultAsync(x => x.Id == id && x.DeletedOn == null); return item; }
注意:该特性要求EF Core版本≥5.0。
2. 全局查询过滤器(推荐批量场景)
针对100+API的重复过滤需求,全局查询过滤器是最优解——它会自动应用到所有Upload实体的查询中,无需在每个接口里重复写过滤逻辑:
在DbContext的OnModelCreating方法中配置全局过滤器:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Upload>() .HasQueryFilter(u => u.DeletedOn == null); // 其他实体配置代码... }
配置后,所有查询(包括Include关联的Upload)都会自动过滤已删除的记录,原代码无需修改即可生效:
public async Task<Challenge?> GetByIdAsync(int id) { var item = await _context.Challenges .Include(x => x.Upload) // 自动应用过滤,只返回DeletedOn为null的Upload .FirstOrDefaultAsync(x => x.Id == id && x.DeletedOn == null); return item; }
若需在个别场景绕过过滤,可使用IgnoreQueryFilters():
var itemWithDeletedUpload = await _context.Challenges .Include(x => x.Upload) .IgnoreQueryFilters() .FirstOrDefaultAsync(x => x.Id == id && x.DeletedOn == null);
3. 投影查询(灵活适配特殊场景)
如果前两种方法不适用,可通过投影构造目标对象,明确指定关联实体的过滤规则:
public async Task<Challenge?> GetByIdAsync(int id) { var item = await _context.Challenges .Where(x => x.Id == id && x.DeletedOn == null) .Select(x => new Challenge { Id = x.Id, // 手动映射Challenge的其他属性 Upload = x.Upload.DeletedOn == null ? x.Upload : null }) .FirstOrDefaultAsync(); return item; }
这种方法需要手动映射所有属性,适合属性较少或需自定义返回结构的场景。
内容的提问来源于stack exchange,提问作者Moasfar Javed
相关产品推荐
相关产品推荐

