You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core自定义OfTypes扩展嵌套关联类型过滤冗余如何优化

问题原因

你遇到的是EF Core TPH(表 per 层次结构)映射的默认行为:PreviousProduct导航属性的声明类型是SubProduct,EF Core在生成关联查询时,默认会把SubProduct下所有派生类对应的ProductTypeId都加入到子查询的IN过滤条件里,你后续写的op.PreviousProduct is AccessProduct判断只会应用到JOIN后的WHERE阶段,不会被下推到JOIN的子查询中,所以出现了多余的类型ID列表。

解决方案1:原生EF Core实现(无需额外库)

直接通过EF.Property访问鉴别器字段,同时结合模型元数据获取对应类型的鉴别器值,避免硬编码ID,EF Core会自动把这个条件下推到JOIN子查询:

// 先从模型中获取AccessProduct对应的ProductTypeId值
var accessProductTypeId = (int)context.Model
    .FindEntityType(typeof(AccessProduct))!
    .GetDiscriminatorValue()!;

var queryable = context
    .Set<Product>()
    .OfTypes(new[] { typeof(SubProduct1), typeof(DeleteProduct) })
    .Where(p => p.CustomerId == customerId && p.CustomerId != null)
    .Where(p => 
        p is SubProduct1 
        || (p is DeleteProduct dp 
            && EF.Property<int>(dp.PreviousProduct, "ProductTypeId") == accessProductTypeId))
    .Select(p => p.ProductId);

解决方案2:借助LINQKit实现(表达式嵌套更友好)

你可以用LINQKit的表达式展开功能,把嵌套的类型判断表达式直接展开到查询树中,EF Core会识别到PreviousProduct的类型过滤要求,自动优化子查询的IN条件:

  1. 先安装LINQKit NuGet包
  2. 调整查询写法:
// 定义可复用的类型判断表达式
private static readonly Expression<Func<Product, bool>> IsAccessProduct = p => p is AccessProduct;

var queryable = context
    .Set<Product>()
    .AsExpandable() // 开启LINQKit表达式展开
    .OfTypes(new[] { typeof(SubProduct1), typeof(DeleteProduct) })
    .Where(p => p.CustomerId == customerId && p.CustomerId != null)
    .Where(p => 
        p is SubProduct1 
        || (p is DeleteProduct dp && IsAccessProduct.Invoke(dp.PreviousProduct)))
    .Select(p => p.ProductId);

调整后生成的SQL中,关联PreviousProduct的子查询过滤条件会自动变为ProductTypeId = 1或者ProductTypeId IN (1),符合你的要求。另外注意你原查询代码里的笔误:多个Where条件里的op应该是p,修正后才能正常编译运行。

内容的提问来源于stack exchange,提问作者Rubenisme

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 15:24:05