Entity Framework Core 6中AsSplitQuery特性不生效该如何处理?
AsSplitQuery未生效的核心原因
AsSplitQuery设计上仅针对集合类型的一对多/多对多导航属性的Include场景生效,你代码中两个Include的ObjectPrototype、ObjectIdentity都是一对一引用导航属性,EF Core对一对一导航默认使用JOIN关联,不会触发拆分查询——因为一对一关联不会产生结果集笛卡尔积,本身就没有拆分的必要。- 排查全局配置是否强制覆盖了查询拆分行为:如果你的DbContext配置中显式设置了
UseQuerySplittingBehavior(QuerySplittingBehavior.SingleQuery),且当前使用的EF Core 6存在小版本Bug时,可能出现单个查询的AsSplitQuery不生效的问题,可以升级到EF Core 6的最新补丁版本规避。 - 检查是否在
AsSplitQuery()之后调用了会重置查询配置的操作,比如IgnoreQueryFilters()等操作放在AsSplitQuery之后,可能导致拆分配置被重置。
调整方案
- 如果你只是验证拆分查询特性,将测试场景改为包含一对多集合导航的Include即可生效,示例代码:
// 假设TObjects有一个一对多的集合导航属性ObjectDetails var result = await ctx.TObjects .Include(o => o.ObjectPrototype) .Include(o => o.ObjectDetails) // 一对多集合导航会触发拆分,单独查询关联表 .AsSplitQuery() .ToListAsync(token);
- 如果你确实需要强制拆分一对一导航的查询(不推荐,会增加数据库往返次数,性能通常不如JOIN),可以手动拆分两次查询再手动关联结果:
// 先查询主表数据 var objects = await ctx.TObjects.ToListAsync(token); // 单独查询关联的ObjectPrototype数据 var prototypeIds = objects.Select(o => o.ObjectPrototypeId).Distinct().ToList(); var prototypes = await ctx.Set<ObjectPrototype>().Where(p => prototypeIds.Contains(p.Id)).ToDictionaryAsync(p => p.Id, token); // 单独查询关联的ObjectIdentity数据 var identityIds = objects.Select(o => o.ObjectIdentityId).Distinct().ToList(); var identities = await ctx.Set<ObjectIdentity>().Where(i => identityIds.Contains(i.Id)).ToDictionaryAsync(i => i.Id, token); // 手动关联导航属性 foreach(var obj in objects) { if (prototypes.TryGetValue(obj.ObjectPrototypeId, out var p)) obj.ObjectPrototype = p; if (identities.TryGetValue(obj.ObjectIdentityId, out var i)) obj.ObjectIdentity = i; }
- 日常使用时确认
AsSplitQuery()的调用位置放在所有Include、Where等查询配置之后,执行方法(ToListAsync等)之前,避免配置被覆盖。
内容的提问来源于stack exchange,提问作者Vlad Kisly
相关产品推荐
相关产品推荐

