EF 1对1 .. *关系

时间:2017-06-13 10:19:22

标签: entity-framework ef-code-first

有没有办法在Entity Framework中创建一对一或多关系?我已经看到很多示例显示1到0 .. *的关系,但我想确保在给定的示例中Foo只有在至少有一个Bar的情况下才能存在。

class Foo
{
   List<Bar> Bars { get; set; }
}

class Bar
{
    public Foo Foo { get; set; }
}

我发现SQL不容易实现这一点,因为我想在Foo表而不是Bar表中使用NOT NULL,但实体框架可以处理吗?

  

我意识到我问了一个错误的问题,因为我实际上正在寻找0..1到1 .. *的关系,这是显着不同的。 This是我想问的问题。

3 个答案:

答案 0 :(得分:1)

在我所知道的任何SQL数据库中都不可能拥有真正的1对1关系。虽然Set理论允许1比1,但实际上,这很难实现。

这基本上是鸡蛋和鸡蛋的情况。您无法创建Foo,因为您没有Bar,并且您无法创建Bar,因为还没有Foo。创建1到1所需的约束基本上阻止您插入任何实际的行。

现在,您可以禁用约束,插入数据然后重新启用它们,但这是一个真正破坏了限制的目的的hacky kludge。

所以只需接受1到0 .. *并继续前进。

答案 1 :(得分:0)

以下示例讨论了实施此类解决方案的难度和可能性。

映射一对一

一对一映射(当需要双方时)也是一件棘手的事情。

让我们想象一下如何使用外键来表示这一点。同样,CarId中的People引用CarId中的Car,以及引用PersonId PersonId的{​​{1}} People PersonId 1}}。

现在如果要插入汽车记录会怎样?为了使此成功,此车记录中必须指定PersonId,因为它是必需的。要使此People有效,CarId中的相应记录必须存在。好的,所以让我们继续插入人事记录。但要成功,有效public class CarEntityTypeConfiguration : EntityTypeConfiguration<Car> { public CarEntityTypeConfiguration() { this.HasRequired(c => c.Person).WithRequiredDependent(p => p.Car); this.HasKey(c => c.PersonId); } } 必须在人员记录中 - 但该车尚未插入!它不可能,因为我们必须先插入推荐的人员记录。但是我们不能插入引用的人员记录,因为它引用了汽车记录,所以必须先插入(外键 - ):)。

所以这不能代表“逻辑”。方式。同样,你必须删除一个外键。你放弃哪一个取决于你。留有外键的一方称为“依赖”,没有外键的一方称为“&#39; principal&#39;”。同样,为了确保依赖项的唯一性,PK必须是FK,因此不支持添加FK列并将其导入模型。

所以这是配置:

public class PersonEntityTypeConfiguration : EntityTypeConfiguration<Person>
{
  public PersonEntityTypeConfiguration()
  {
    this.HasRequired(p => p.Car).WithRequiredPrincipal(c => c.Person);
  }
}

到现在为止你真的应该已经掌握了它的逻辑:)请记住你也可以选择另一面,只需要小心使用WithRequired的Dependent / Principal版本(你仍然需要配置PK)汽车)。

min()

如果您检查数据库架构,您会发现它与一对一或零解决方案的情况完全相同。这又是因为这不是由架构强制执行的,而是由EF本身强制执行的。所以再次注意:)

答案 2 :(得分:0)

尽可能接近是这样的:

class Foo
{
    List<Bar> Bars { get; set; }

    [Required]
    public int PrimaryBarId { get; set; }
    public Bar PrimaryBar { get; set; }
}

class Bar
{
    public Foo Foo { get; set; }
}

但请注意,数据库不会强制执行

aFoo.PrimaryBar.FooId == aFoo.Id

由于循环FK,这种模型很难更新。