EF使用Include过滤非必填关联字段生成LEFT JOIN,如何获取准确查询结果?
问题原因
你把过滤规则写在了Include的关联过滤条件里,这个语法仅用来在预加载关联数据时过滤需要加载的ContactAddress条目,不会对主表Contact的查询范围产生任何限制。因此EF默认生成LEFT JOIN来保证所有联系人都被返回,最终统计的总数自然等于全表数据量。
解决方法
不需要强制指定JOIN类型,直接给主查询增加Where筛选条件即可,EF会自动生成符合要求的SQL语句,得到准确的筛选结果:
IQueryable<Contact> query = context.Contacts; if (searchModel.SelectedCountries?.Count() > 0) { List<int> country_ids = searchModel.SelectedCountries.Select(x => x.Id).ToList(); // 新增筛选:仅保留存在符合条件地址的联系人 query = query.Where(c => c.Addresses.Any(a => a.CountryId.HasValue && country_ids.Contains(a.CountryId.Value) && a.IsPrimary == true)); // 如果只需要统计总数,不需要加载关联地址,可以删掉下面的Include语句 // query = query.Include(c => c.Addresses.Where(a => country_ids.Contains(a.CountryId.Value) && a.IsPrimary == true)); } int totalResultsCount = await query.CountAsync().ConfigureAwait(false);
上述代码中新增的Any条件会让EF生成EXISTS子查询或者INNER JOIN,最终统计出的总数就是符合条件的联系人数量,和你手动修改JOIN类型得到的结果一致。
如果后续查询需要返回联系人实体同时加载符合条件的地址,保留对应的Include语句即可。
内容的提问来源于stack exchange,提问作者Sebastian
相关产品推荐
相关产品推荐

