1

我有类似如下的代码第一种模式:实体框架代码优先 - 可选/需要双向导航

public class TestContext : DbContext 
{ 
    public DbSet<Class1> Class1s { get; set; } 
    public DbSet<Class2> Class2s { get; set; } 
} 

public class Class1 
{ 
    public int Class1Id { get; set; } 
} 

public class Class2 
{ 
    public int Class2Id { get; set; } 

    public int Class1Id { get; set; } 
    public Class1 Class1 { get; set; } 
} 

有零参照各Class1的对象很多的Class2对象。每个Class2对象都必须具有对Class1对象的引用。

我想什么做的是从class1的Class2中的可选引用(跟踪与Class1的对象相关联的Class2中的一个对象),所以我加了两个属性:

public class Class1 
{ 
    public int Class1Id { get; set; } 
    public int? Class2Id { get; set; } 
    public Class2 Class2 { get; set; } 
} 

现在我收到以下错误,当我运行添加迁移:

无法确定 类型“ConsoleApplication15.Class2”和“ConsoleApplication15.Class1”之间的关联的主要终点。 必须使用关系流畅API或数据注释,明确配置此关联的主体端 。

其他StackOverflow的答案表明,解决办法是规定对因外键字段:

public class Class2 
{ 
    [Key, ForeignKey("Class1")] 
    public int Class2Id { get; set; } 

    public int Class1Id { get; set; } 
    public Class1 Class1 { get; set; } 
} 

我的外接迁移命令现在完成,但迁移创建如下:

public override void Up() 
{ 
    DropForeignKey("dbo.Class2", "Class1Id", "dbo.Class1"); 
    DropIndex("dbo.Class2", new[] { "Class1Id" }); 
    DropColumn("dbo.Class2", "Class2Id"); 
    RenameColumn(table: "dbo.Class2", name: "Class1Id", newName: "Class2Id"); 
    DropPrimaryKey("dbo.Class2"); 
    AddColumn("dbo.Class1", "Class2Id", c => c.Int()); 
    AlterColumn("dbo.Class2", "Class2Id", c => c.Int(nullable: false)); 
    AddPrimaryKey("dbo.Class2", "Class2Id"); 
    CreateIndex("dbo.Class2", "Class2Id"); 
    AddForeignKey("dbo.Class2", "Class2Id", "dbo.Class1", "Class1Id"); 
} 

这看起来并不像我想要的那样。它放弃了Class2上的主键,并且它在最后添加的外键完全错误。

如何描述我对EF的要求,以便生成正确的模型?

回答

1

问题是EF按照惯例想要创建one-to-one relationship,并且在这种情况下,您需要指定哪个实体是主体。

如果要在每个实体中使用不同的PK创建一对一关系,则无法在两个实体中声明FK属性。当您配置one-to-one relationships时,实体框架要求该依赖项的主键也是外键(这是您在上一个场景中尝试执行的操作)。

一种解决方案可以删除FK属性(Class1IdClass2Class2IdClass1),并覆盖在你的上下文OnModelCreating方法添加此配置:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<Class2>() 
       .HasRequired(c2 => c2.Class1). 
       .WithOptional(c1=>c1.Class2); 
} 

如果你想与FK性质的工作你可以创建两个单独的关系,如下所示:

 modelBuilder.Entity<Class2>() 
        .HasRequired(s => s.Class1) 
        .WithMany() 
        .HasForeignKey(s => s.Class1Id); 

     modelBuilder.Entity<Class1>() 
        .HasOptional(s => s.Class2) 
        .WithMany() 
        .HasForeignKey(s => s.Class2Id); 

我认为这最后的解决方案更适合您尝试的场景 实现。

+0

这正是我需要的 - 非常感谢。 –