entity-framework-core - EF Core 5:Include With Where 语句后跟 ThenInclude——继承问题
问题描述
我有一个正在开发的项目。首先,模式非常简单;我有一个用户,这个用户在很多仓库工作。有不同类型的仓库,但是——对于这个例子——我会保持简单。在此示例中,我们有一个继承自 Warehouse 的 ManagedWarehouse。
以下是课程:
public class User
{
public int UserId { get; set; }
public string Name { get; set; }
public List<Warehouse> Warehouses { get; set; }
}
public class Warehouse
{
public int WarehouseId { get; set; }
public bool IsActive { get; set; }
}
public class ManagedWarehouse : Warehouse
{
public int GeneralManagerId { get; set; }
public User GeneralManager { get; set; }
}
现在我正在创建一个 EF 查询,它允许我获取所有用户以及他们工作的 ACTIVE 仓库。另外,如果仓库是a ManagedWarehouse
,也会退回GeneralManager。
这是我的查询:
public IQueryable<User> GetUsers()
{
return this.DbContext.Users.Include(u => u.Warehouses.Where(wh => wh.IsActive)).ThenInclude(wh => ((ManagedWarehouse)wh).GeneralManager);
}
这似乎是一个简单的查询,但它不会编译。它抱怨这个电话是模棱两可的:
严重性代码 描述 项目文件行抑制状态错误 CS0121 调用在以下方法或属性之间不明确: 'EntityFrameworkQueryableExtensions.ThenInclude<TEntity, TPreviousProperty, TProperty>(IIncludableQueryable<TEntity, IEnumerable>, Expression<Func<TPreviousProperty, TProperty>>) ' 和 'EntityFrameworkQueryableExtensions.ThenInclude<TEntity, TPreviousProperty, TProperty>(IIncludableQueryable<TEntity, TPreviousProperty>, Expression<Func<TPreviousProperty, TProperty>>)'
如果我删除.Where(wh => wh.IsActive)
,它会编译,但是 - 再次 - 我只希望返回活动的仓库。如何在返回所需数据的同时使其“明确”?谢谢你。
解决方案
EF CoreThenInclude
模式从一开始就存在 C# IntelliSense/编译器的问题,因为定义了两个重载 - 一个 forT
和一个 for IEnumerable<T>
. 由于这两个重载都适用,看起来编译器只有在您使用 的某些直接属性/方法时才能推断出正确的重载T
,否则(参数上的任何其他运算符,包括as
问题中的强制转换等)它会失败。
这是最小的可重现示例:
class A
{
public IEnumerable<B> Bs { get; set; }
}
class B
{
public C C { get; set; }
}
class C
{
}
static void Test(IQueryable<A> source)
{
var includable = source
.Include(a => a.Bs);
var compiles = includable.ThenInclude(b => b.C);
var doesNotCompile = includable.ThenInclude(b => ((B)b).C); // CS0121
}
强制转换是多余的,因为b
type is B
,但它破坏了编译器。有趣的是,这只发生在前一个表达式返回确切的接口(IEnumerable<T>
在这种情况下)时 - 如果表达式是派生类/接口(在这种情况下IReadOnlyCollection<T
,List<T>
等),编译器推断有效。
这就是ThenInclude
过滤失败的原因Include
,因为它返回IEnumerable<T>
,即使Include
如果集合导航属性类型是IEnumerable<T>
(由 EF Core 支持)而不是通常的ICollection<T>
或其他派生类型,它也会发生。
话虽如此,我不确定这是否应该被视为(并报告)为 EF Core API 设计错误或 C# 编译器问题。但无论哪种情况,我认为它不会很快得到解决。因此,作为一种解决方法,让编译器通过显式指定参数类型来识别所需的重载:
.ThenInclude((Warehouse wh) => ((ManagedWarehouse)wh).GeneralManager)
// ^^^
推荐阅读
- excel - 具有包含空格和逗号的路径的工作簿的 VBA ADO 连接字符串
- android - Hilt:为什么 ApplicationComponent 范围内的一个类被创建了两次?
- php - 如何显示与php pdo具有多个一对多和多对多关系的所有记录?
- javascript - Google Apps 脚本 Google Sheets Gmail 处理新电子邮件 追加行数组
- reactjs - TypeError: Object(...) is not a function with useEffect React with latest version
- python - macOS 后台 PyQt 线程执行超时
- android - ScrollView 中的线性视图,阵列适配器在新项目上增长而不是下降
- python - 没有名为“ray.rllib.agents.ppo.ppo_policy”的模块
- javascript - 使用simple-git,只能得到一个提交工作
- python - 无法安装ggplot