我有一个遗留数据库,不能使用两个实体在每个实体中都具有外键属性来进行更改:
EntityOne
ForeignKey1 (pointing to EntityTwo.ForeignKey2)
EntityTwo
ForeignKey2 (pointing to EntityOne.ForeignKey1)
Run Code Online (Sandbox Code Playgroud)
这些外键指向彼此。如何将这种关系与EF6对应?如果不可能,是否有任何解决方法?
我用一个测试数据库进行了测试,该数据库实际上具有一个从EntityOne到EntityTwo的外键关系,另一个从EntityTwo到EntityOne的外键关系,并自动生成模型(首先从数据库获取代码),并没有在两个表之间创建任何关系:
public partial class EntityFrameworkTesting : DbContext
{
public EntityFrameworkTesting()
: base("name=EntityFrameworkTesting")
{
}
public virtual DbSet<EntityOne> EntityOne { get; set; }
public virtual DbSet<EntityTwo> EntityTwo { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
}
Run Code Online (Sandbox Code Playgroud)
通过一些额外的尝试,我成功地在这些实体之间建立了关系。但是,我必须从POCO类中删除外键属性,才能使用MapKey函数。我仍然想访问外键,但是当再次添加外键属性时,收到一条错误消息:“ ForeignKey2:名称:类型中的每个属性名称都必须是唯一的。属性名称'ForeignKey2'已经定义。” 。
基本上,我正在寻找现在具有的关系功能,但是在POCO类上添加了外键属性。
modelBuilder.Entity<EntityTwo>()
.HasRequired(entity => entity.EntityOne)
.WithRequiredDependent(entity => entity.EntityTwo)
.Map(m => m.MapKey("ForeignKey2"));
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您希望使用共享主键,这意味着依赖实体的 PK 也是主体实体的 FK(并引用主体实体的 PK),从而强制执行 1..0 关系。您可以查看此答案以了解其配置方式。
如果您无法更改数据库架构,那么您在 EF6 中就不走运了。EF6 不支持 FK 引用主键以外的任何候选键。
EFCore 支持 FK 引用备用候选键,但仍然不会创建两个相互引用的 FK - 只会创建依赖表中的 FK(或者通过我刚才的有限测试看来是这样)。您可以通过以下 FluentAPI 配置来执行此操作(假设EntityOne是主体实体):
modelBuilder.Entity<EntityOne>()
.HasAlternateKey( eo => eo.ForeignKey1 );
modelBuilder.Entity<EntityTwo>()
.HasOne( et => et.EntityOne )
.WithOne( eo => eo.EntityTwo )
.IsRequired()
.HasForeignKey<EntityTwo>( et => et.ForeignKey2 )
.HasPrincipalKey<EntityOne>( eo => eo.ForeignKey1 );
Run Code Online (Sandbox Code Playgroud)
EntityOne.ForeignKey1应该可以为空。测试时,我必须手动指定 Has*Key 方法的类型参数,不知道为什么。