我在 .net8 ef core 中使用 postgres 数据库和代码优先方法。
我有这两门课:
public class Soggetto
{
public long Id { get; set; }
public virtual Azienda Azienda { get; set; }
public long AziendaId { get; set; }
}
public class Soggetto
{
public long Id { get; set; }
public virtual Soggetto Soggetto { get; set; }
public long SoggettoId { get; set; }
}
以及这两个流畅的配置:
public class SoggettoConfiguration : BaseAziendaAnagraficaEntityConfiguration<Soggetto>
{
public override void Configure(EntityTypeBuilder<Soggetto> builder)
{
base.Configure(builder);
builder
.HasOne(soggetto => soggetto.Azienda)
.WithOne(azienda => azienda.Soggetto)
.HasForeignKey<Soggetto>(x => x.AziendaId);
}
}
public class AziendaConfiguration : BaseEntityConfiguration<Azienda>
{
public override void Configure(EntityTypeBuilder<Azienda> builder)
{
base.Configure(builder);
builder
.HasOne(azienda => azienda.Soggetto)
.WithOne(soggetto => soggetto.Azienda)
.HasForeignKey<Azienda>(azienda => azienda.SoggettoId);
}
}
因此,当 EF 生成迁移代码时,我在 Azienda 表中找到 Soggetto 的外键,而在 Soggetto 表中没有 Azienda 的外键。 我的期望是在 Azienda 表中找到 FK: SoggettoId 并在 Soggetto 表中找到 AziendaId。
有什么想法吗?
看来你对一对一关系有一个小误区。基本上它在 EF Core 文档中有所介绍 - 一对一关系:
必需的关系确保每个依赖实体必须与某个主体实体关联。 但是,主体实体始终可以在没有任何从属实体的情况下存在。也就是说,必需的关系并不表明总是存在依赖实体。 EF 模型中没有任何方法,关系数据库中也没有标准方法来确保主体与依赖项关联。 如果需要这样做,则必须在应用程序(业务)逻辑中实现。请参阅所需导航了解更多信息。
如果您想模拟“真正”的一对一关系,通过 EF 的唯一选择是使用 拥有的实体类型,如文档中先前链接的“必需导航”部分中所述:
此规则有一个例外 - 当主体类型和依赖类型共享关系数据库中的同一个表或包含在文档中时。对于拥有的类型或共享同一个表的非拥有的类型,可能会发生这种情况。这种情况下,从主体到依赖的导航属性可以标记为required,表明依赖必须存在。
如果表之间有多个一对一的关系,那么您将需要有多个属性。例如,沿着这些思路(未测试):
public class Soggetto
{
public long Id { get; set; }
public virtual Azienda ChildAzienda { get; set; }
public long ParentAziendaId { get; set; }
public virtual Azienda ParentAzienda { get; set; }
}
public class Azienda
{
public long Id { get; set; }
public long ParentSoggettoId { get; set; }
public virtual Soggetto ParentSoggetto { get; set; }
public virtual Soggetto ChildSoggetto { get; set; }
}
并使用 Fluent API 对应映射它们。