EF - WithOptional - 左外连接?

8
有以下两个具有导航属性的一对一模型:
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"));

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

这一切都很好,除了当不需要时,在所有查询中它会为 Foo 生成带有 'Left Outer Join' 到 Bar 的 SQL。

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

仔细查看发现它只返回了 Bar 的 Id。

在 Stack Overflow 上搜索 可以看到大多数建议使用 .WithMany 而不是 .WithOptional,但我需要导航属性。

有什么建议吗?


如果你考虑一下,实际上不存在1:1这样的东西,除非你使用共享主键,因为按照它们的本质,关键字必须是唯一的。当然,你可以在1:*上放置一个唯一约束来创建有效的1:1,但这是一种“虚拟”的1:1,而不是真正的物理1:1。EF不支持这样的约束,所以这是不可能的。这就是为什么连接存在的原因,因为EF只能假设这是1:*。 - Erik Funkenbusch
1个回答

4
这是一对一外键关系的标准行为,无法避免。EF内部维护一个类似于int? BarId的隐藏属性,用于实体Foo
要想摆脱LEFT OUTER JOIN并保留双向导航属性,唯一的方法是如果你能够承担改变Bar数据库模型(表)的代价,使用(默认的EF一对一模型)共享主键关联,基本上只需要从流畅配置中删除Map调用。
HasRequired(x => x.Foo)
    .WithOptional(x => x.Bar);

在此模型中,Bar表将不包含FooId FK列,而是PK列Id将不再是标识并且还将作为FK引用Foo表。
这样EF就不需要关心在Foo中维护BarId,因为它知道如果有对应的Bar,它的Id将与Foo.Id相同。
如果您无法更改数据库设计,则很遗憾 - 您必须要么接受LEFT OUTER JOIN,要么舍弃Foo.Bar导航属性,并将关系配置为单向一对多关系,正如您已经提到的那样。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接