我们需要在以下实体之间定义一对一关系:
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);
当我们查询Foo
和Include(x => x.Bar)
时,它会创建一个LEFT OUTER JOIN bars ON Foo_ID = Bar_ID
的SQL查询,这是错误的。
我们需要将其更改为LEFT OUTER JOIN bars on Foo_ID = Bar_Foo_ID
,但我不确定实体框架是如何支持的,因为我们的数据库中没有外键,而Bar_ID
则为PrimaryKey
我知道一个Bars
可能有多个Foo
,但有没有办法强制实行一对一关系?
创建Foo
后,始终会为其创建Bar
。
答案 0 :(得分:2)
对于旧数据,您可以使用以下内容:
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);
答案 1 :(得分:1)
我理解它的方式,你在Bar_Foo_ID
表中有一个名为Bar
的列,它必须用作Bar_ID
表中PK Bar
列的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
来取消关联。如果您想在删除Bar
时实际删除关联的Foo
,则必须使用代码手动执行此操作。