【问题标题】:Entity Framework Core 3, get foreign key without joinEntity Framework Core 3,无需加入即可获取外键
【发布时间】:2020-06-12 14:17:49
【问题描述】:

使用 EF Core,我想获取外键而不需要与这些表连接。

我有两张桌子:

  • 用户 [id, name, system(FK)]
  • 系统 [id, name]

我希望能够从Users 表中获取System 的外键。如果没有选择除 FK 之外的其他属性,我会认为 EF 会足够聪明地删除连接,但这不是我在测试时看到的。

我试过了:

var userSystem = DBContext.Users
                          .Where(a => a.Id == 1)
                          .Select(a => new { UserId = a.id, SystemId = a.system.Id })
                          .FirstOrDefault();

但是查看生成的 SQL 查询,它在系统表上包含一个不必要的 LEFT JOIN。关于如何让 EF 在没有加入的情况下生成代码的任何想法?

注意:在此示例中,连接显然不是问题,但我还有其他查询,其中有很多 FK 被提取,具有严格的性能要求。

【问题讨论】:

  • Any ideas as to how I can make EF generate code without the join?- 那么如何将用户 ID 映射到过滤器?
  • 正如你提到的 systemFK 那么它应该是 int 我猜。而且你不能在Select 中使用a.system.Id。如果您在 Users 表中有 SystemId,那么只需使用 select as Select(a => new { UserId = a.id, SystemId = a.SystemId })
  • 向我们展示您的模型的代码
  • 用户实体中的 System(FK) 列是否设置为可空或不可空?

标签: c# entity-framework-core


【解决方案1】:

它曾经足够智能(将来可能会),但 EF Core 3.x 查询管道重写出现了一些问题,因此目前它会为这种情况和许多其他情况生成不必要的连接(特别是对于自有实体而言更明显)具有表拆分的类型)。

在 v3.x 中解决此问题的唯一方法是使用 EF.Property 方法,这需要知道影子 FK 属性名称及其类型。这当然不好且容易出错,但这是当前 EF Core 缺陷的代价。

在你的情况下,它可能是这样的:

SystemId = EF.Property<int?>(a, "systemId")

可以通过从 EF Core 元数据中检索来避免硬编码 FK 属性名称:

var fkPropertyName = DBContext.Model
    .FindEntityType(typeof(User))
    .FindNavigation(nameof(User.system))
    .ForeignKey.Properties[0].Name;

然后

SystemId = EF.Property<int?>(a, fkPropertyName)

您仍然需要对类型进行硬编码。

当然,您可以通过在实体模型中定义和使用显式 FK 属性来避免这一切。

【讨论】:

  • 谢谢!我不知道有可能有一个明确的 FK 属性,但我现在尝试了它,它工作得很好。在我看来,这应该是一种最佳实践。
猜你喜欢
  • 2022-09-22
  • 1970-01-01
  • 1970-01-01
  • 2020-06-03
  • 2018-09-28
  • 2016-12-16
  • 1970-01-01
  • 1970-01-01
  • 2019-02-13
相关资源
最近更新 更多