繁体   English   中英

具有单独ID属性的EF6一对一关系

[英]EF6 One-To-One relationship with separate ID property

我们需要在以下实体之间定义一对一关系:

public class Foo
{
    [Key, Column("Foo_ID")]
    public int Id { get; set; }

    public Bar Bar { get; set; }
}

public class Bar
{
    [Key, Column("Bar_ID")]
    public int Id { get; set; }

    [Column("Bar_Foo_ID")]
    public int? FooId { get; set; }

    public Foo Foo { get; set; }   
}

我们需要迁移旧版软件,并让它们现在并排运行。 所以我们不能改变任何关系。 遗憾的是,数据库中没有定义外键。

modelBuilder.Entity<Foo>()
            .HasOptional(a => a.Bar)
            .WithRequired(x => x.Foo)
            .WillCascadeOnDelete(true);

当我们查询FooInclude(x => x.Bar)它会创建一个带有LEFT OUTER JOIN bars ON Foo_ID = Bar_ID的SQL查询LEFT OUTER JOIN bars ON Foo_ID = Bar_ID这是错误的。

我们需要LEFT OUTER JOIN bars on Foo_ID = Bar_Foo_ID其更改为LEFT OUTER JOIN bars on Foo_ID = Bar_Foo_ID ,但我不确定Entity Framework是如何支持的,因为我们的DB和Bar_ID没有外键作为PrimaryKey。

我知道一个Foo可能有多个Bars ,但是有没有办法强制实现一对一关系?

创建Foo ,始终会为其创建一个Bar

对于旧数据,您可以使用以下内容:

1:0-1关系基本上是1:许多关系的特殊形式。

因此,您可以在实体框架中将关系配置为1:many,并可能向外键属性添加唯一索引,以强制执行max的约束。 一个相关的条目。

public class Foo
{
    [Key, Column("Foo_ID")]
    public int Id { get; set; }

    // this can't be a single reference property unfortunately... but it will only contain 0 or 1 object when working with it.
    public ICollection<Bar> Bars { get; set; }
}

public class Bar
{
    [Key, Column("Bar_ID")]
    public int Id { get; set; }

    [Index(IsUnique = true)]
    [Column("Bar_Foo_ID")]
    public int? FooId { get; set; }

    public Foo Foo { get; set; }   
}

modelBuilder.Entity<Foo>()
            .HasMany(a => a.Bars)
            .WithRequired(x => x.Foo)
            .HasForeignKey(x => x.FooId)
            .WillCascadeOnDelete(true);

我理解它的方式,你在Bar表中有一个名为Bar_Foo_ID的现有列,它必须用作Bar表中PK Bar_ID列的FK。

这是可能的,但EF6对这种关系的支持有限,特别是不支持显式FK属性。 所以你必须从模型中删除FooId属性:

public class Bar
{
    [Key, Column("Bar_ID")]
    public int Id { get; set; }

    public Foo Foo { get; set; }   
}

并使用以下流畅的配置:

modelBuilder.Entity<Foo>()
    .HasOptional(a => a.Bar)
    .WithOptionalPrincipal(x => x.Foo)
    .Map(m => m.MapKey("Bar_Foo_ID"))
    .WillCascadeOnDelete(true);

MapKey是指定FK列名。 WithOptionalPrincipal用于指定它可以为空(而WithRequired用于非可空)。

请注意,对于可选关系,EF6会以不同方式处理级联删除。 它不是删除相关记录,而是通过将FK设置为null来取消它们。 如果您想在删除Foo时实际删除关联的Bar ,则必须使用代码手动执行此操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM