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

這正是我需要的 - 非常感謝。 –