如何在LINQ与Entity Framework Core中筛选子查询
如何筛选关联实体:查询Invoice时仅包含Active=true的Payment
你的需求是查询Invoice实体时,仅加载其关联的Active == true的InvoicePayment(以及Active == true的InvoiceLine),但当前代码的写法存在逻辑错误:
原代码中.Include(inv => inv.Payments).Where(pm => pm.Active)的Where是作用于Invoice集合的过滤条件,而非筛选关联的Payments集合。这会导致EF只返回那些至少存在一个Active=true的Payment的Invoice,而不是让每个Invoice仅包含符合条件的Payments。
正确实现方式(EF Core 5+)
EF Core 5及以上版本支持筛选包含(Filtered Include),可以直接在Include的表达式内添加过滤条件,实现仅加载符合要求的关联实体:
public async Task<Invoice> InvoiceAsync(Expression<Func<Invoice, bool>> predicate) { return await ExecSingleAsync( this.GetDbSet<Invoice>() .Include(inv => inv.Actions) .Include(inv => inv.Account) .Include(inv => inv.Customer) // 筛选Active=true的Payments .Include(inv => inv.Payments.Where(pm => pm.Active)) // 筛选Active=true的Lines .Include(inv => inv.Lines.Where(ln => ln.Active)) .Where(inv => inv.Active) .Where(predicate) ); }
额外优化建议
将实体集合属性的类型从
IEnumerable<T>改为ICollection<T>,这更符合EF对关联集合的跟踪要求,也能避免潜在的延迟加载或过滤问题:// Invoice.cs中修改 public ICollection<InvoiceLine> Lines { get; set; } = new HashSet<InvoiceLine>(); public ICollection<InvoicePayment> Payments { get; set; } = new HashSet<InvoicePayment>(); public ICollection<InvoiceAction> Actions { get; set; } = new HashSet<InvoiceAction>();确认
ExecSingleAsync方法会正确处理查询,若需允许筛选后关联集合为空的场景,可考虑使用ExecSingleOrDefaultAsync替代。
内容的提问来源于stack exchange,提问作者SteinTech
相关产品推荐
相关产品推荐

