如何在EF Core中过滤关联实体,仅获取指定品牌的PurchaseTrans?
问题解决:过滤关联实体中的指定数据
你的核心问题是:当前查询会返回包含目标品牌交易的采购主单(PurchaseMaster),但同时会加载该主单下所有采购交易(PurchaseTrans),而你只需要其中属于目标品牌的交易记录。
为什么原有代码无效
你用Any/All是在筛选主表(PurchaseMaster)——判断某个主单是否存在符合品牌的交易,符合条件的主单会被完整返回,包括其所有关联的PurchaseTrans,这就是为什么你会拿到全部3种品牌的数据。Include默认会加载主单下的所有关联集合,不会自动应用主表的过滤条件到子集合上。
解决方案
下面提供三种可行的实现方式,根据你的需求选择:
方式1:使用投影(推荐,灵活可控)
直接通过投影构建你需要的数据结构,精准过滤子集合:
var ressales = await _dbcontext.s_purmas .Where(r => r.sdate >= dtfrom && r.sdate <= dtto) .Where(r => r.cancel == "0") .Where(p => p.PurchaseTrans.Any(t => EF.Functions.Like(t.Item.brand_name, brand))) .Select(p => new { // 选择PurchaseMaster需要的字段 Id = p.id, SDate = p.sdate, RefNo = p.refno, // 过滤符合品牌的PurchaseTrans及其关联的Item PurchaseTrans = p.PurchaseTrans .Where(t => EF.Functions.Like(t.Item.brand_name, brand)) .Include(t => t.Item) .ToList() }) .OrderBy(r => r.Id) .ToListAsync();
如果需要返回强类型,可以定义一个DTO类来替代匿名类型。
方式2:过滤Include(EF Core 5.0+支持)
如果你需要返回完整的PurchaseMaster实体,且只保留符合条件的PurchaseTrans,可以使用EF Core的过滤Include功能:
var ressales = await _dbcontext.s_purmas .Include(c => c.PurchaseTrans.Where(t => EF.Functions.Like(t.Item.brand_name, brand))) .ThenInclude(c => c.Item) .Where(r => r.sdate >= dtfrom && r.sdate <= dtto) .Where(r => r.cancel == "0") .Where(p => p.PurchaseTrans.Any(t => EF.Functions.Like(t.Item.brand_name, brand))) .OrderBy(r => r.id) .ToListAsync();
注意:这种方式会修改实体的关联集合,如果你之后要将实体保存回数据库,要小心不要误删其他交易记录。
方式3:从子表发起查询
反过来从PurchaseTrans开始查询,关联主表,这样自然只获取符合品牌的交易:
var ressales = await _dbcontext.PurchaseTrans .Include(t => t.PurchaseMaster) .Include(t => t.Item) .Where(t => EF.Functions.Like(t.Item.brand_name, brand)) .Where(t => t.PurchaseMaster.sdate >= dtfrom && t.PurchaseMaster.sdate <= dtto) .Where(t => t.PurchaseMaster.cancel == "0") .GroupBy(t => t.PurchaseMaster) .Select(g => new { PurchaseMaster = g.Key, FilteredTrans = g.ToList() }) .OrderBy(x => x.PurchaseMaster.id) .ToListAsync();
这种方式适合你更关注交易记录,同时需要关联主表信息的场景。
内容的提问来源于stack exchange,提问作者Shan
相关产品推荐
相关产品推荐

