【问题标题】:EF - WithOptional - Left Outer Join?EF - WithOptional - 左外连接?
【发布时间】:2017-04-05 12:16:59
【问题描述】:

使用以下一对一模型,均具有导航属性:-

public class Foo
{
    public int Id { get; set; }
    
    public virtual Bar Bar { get; set; }
}

public class Bar
{
    public int Id { get; set; }

    public virtual Foo Foo { get; set; }
}

Foo 有一个可选的Bar

Bar 有一个必需的Foo

我在 Bar 上有以下映射:-

HasRequired(x => x.Foo)
      .WithOptional(x => x.Bar)
      .Map(x => x.MapKey("FooId"));

这会在名为 'FooId' 的 Bar 表上创建外键。

所有这一切都很好,除了它为 Foo 生成 sql,并在不需要时在所有查询中使用“左外连接”到 Bar

SELECT ..
[Extent2].[Id] AS [Id1]
FROM  [dbo].[Foo] AS [Extent1]
LEFT OUTER JOIN [dbo].[Bar] AS [Extent2] ON [Extent1].[Id] = [Extent2].[FooId]

仔细查看只会返回 Bar 的 ID。

Searching 堆栈我可以看到大多数使用.WithMany 而不是.WithOptional 的建议,但我需要导航属性。

有什么建议吗?

【问题讨论】:

  • 如果你想一想,真的没有 1:1 这样的事情,除非你正在做一个共享的主键,因为键在本质上必须是唯一的。当然,您可以对 1:* 设置唯一约束以创建有效的 1:1,但这是一种“虚拟”1:1,而不是真正的物理 1:1。 EF 不支持这样的约束,所以它是不可能的。这就是连接存在的原因,因为 EF 只能假设这是一个 1:*

标签: c# entity-framework entity-framework-6


【解决方案1】:

这是一对一 FK 关联的标准行为,无法避免。 EF 所做的是在内部为Foo 实体维护一个隐藏(影子)属性,例如int? BarId

摆脱LEFT OUTER JOINs 并保持双向导航属性的唯一方法是,如果您有能力更改 Bar db 模型(表)以使用(默认 EF 一对一-one 模型)Shared Primary Key Association 基本上从流利的配置中删除 Map 调用:

HasRequired(x => x.Foo)
    .WithOptional(x => x.Bar);

在此模型中,Bar 表将不包含 FooId FK 列,但 PK 列 Id 将不再是标识,并且还将用作引用 Foo 表的 FK。

这使得 EF 不必关心在 Foo 中维护一个 BarId,因为它知道如果有对应的 Bar,它将与 IdFoo.Id 相同。

如果你不能改变数据库设计,那么你就倒霉了——你要么忍受LEFT OUTER JOINs,要么牺牲Foo.Bar导航属性并将关系配置为单向一对多正如你已经提到的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-01
    • 1970-01-01
    • 2017-12-21
    • 2016-10-02
    • 2018-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多