Entity Framework 5/6自引用Include技巧失效,不改签名如何兼容?
EF Core 5.0 及以上版本强化了 Include 方法的表达式校验逻辑,要求传入的表达式必须指向实体的有效属性,不再支持 Include(w => w) 这种直接引用实体本身的写法,这就是你升级后抛出异常的直接原因。
以下两种方案都可以在不修改方法签名的前提下解决问题,完全兼容EF Core 5/6/7+所有版本,不会改变原有查询逻辑:
方案1:直接强制类型转换
IIncludableQueryable<out TEntity, out TProperty> 接口的两个泛型参数均为 协变 ,且该接口仅用于编译期的ThenInclude类型推断,运行时EF Core不会依赖该接口的泛型参数构建查询,因此可以安全地将已经调用过Include的查询对象直接转换为目标返回类型:
private static IIncludableQueryable<Widget, Widget> WidgetQueryIncludeFringles(IQueryable<Widget> widQuery) { return widQuery .Include(w => w.Fringles).ThenInclude(f => f.Bauble) as IIncludableQueryable<Widget, Widget>; }
如果担心as转换返回空的极端场景,可以替换为显式强制转换,效果完全一致。
方案2:封装通用扩展方法(可读性更佳)
如果这类可组合查询方法较多,可以封装一个通用扩展方法统一处理转换,避免重复写类型转换代码:
首先定义通用扩展:
public static class QueryableExtensions { public static IIncludableQueryable<TEntity, TEntity> ToRootIncludable<TEntity>(this IQueryable<TEntity> query) { return query as IIncludableQueryable<TEntity, TEntity>; } }
修改原方法调用即可:
private static IIncludableQueryable<Widget, Widget> WidgetQueryIncludeFringles(IQueryable<Widget> widQuery) { return widQuery .Include(w => w.Fringles).ThenInclude(f => f.Bauble) .ToRootIncludable(); }
内容的提问来源于stack exchange,提问作者CarlJ
相关产品推荐
相关产品推荐

