3

我目前正在清理一個相當大的數據庫的過程。部分數據庫的關係是一對一或一對映射。具體來說:映射一對零或一與EF7

User -> UserSettings 

並非所有用戶都有用戶設置,但用戶設置不能在沒有用戶的情況下存在。不幸的是,表格已經存在。 User有一個PK ID。 UserSettings有一個PK ID和一列,User_Id_Fk,在這個時間點上,它不是一個真正的FK(沒有定義關係)。

我正在修復這個問題,並且已經從數據庫角度通過SQL完成了這些工作,並已通過測試進行了確認。 (增加了FK約束,在User_Id_Fk上增加了一個唯一約束)。這一切都在UserSettings表上完成。 (注意:這裏我沒有使用EF遷移,現在我必須手動編寫SQL)。

但是,我現在需要連接現有的應用程序以正確處理這個新的映射。該應用程序使用ASP.NET Core 1.0和EF7。以下是現有數據模型的(縮短的)版本。

public class User 
{ 
    public int Id { get; set; } 

    public virtual UserSettings UserSettings { get; set; } 
} 

public class UserSettings 
{ 
    public int Id { get; set; } 

    [Column("User_Id_Fk")] 
    public int UserId { get; set; } 

    [ForeignKey("UserId")] 
    public virtual User User { get; set; } 
} 

我有這種良好的映射,以及:

builder.Entity<UserSettings>() 
      .HasOne(us => us.User) 
      .WithOne(u => u.User) 
      .IsRequired(false); 

當我去運行應用程序和訪問數據庫中的這些項目,我得到遵循的神祕的一組消息有此錯誤與直接回我的應用程序:

ArgumentNullException: Value cannot be null. 
Parameter name: navigation 
Microsoft.Data.Entity.Utilities.Check.NotNull[T] (Microsoft.Data.Entity.Utilities.T value, System.String parameterName) <0x10d28a650 + 0x00081> in <filename unknown>, line 0 

做研究後沒有任何信息,有人提到,UserSettings類的ID必須是相同的外鍵,LIK è這樣:

public class UserSettings 
{ 
    [Key, ForeignKey("User")] 
    public int Id { get; set; } 

    public virtual User User { get; set; } 
} 

我真的沒有這個作爲一個選項,正在使用的數據塊是我無法控制的在這一點上的其他應用程序。那麼,我在這裏?我只需要維持一個1:多的映射(其中可能是現在雖然沒有),但對於1:0..1映射沒有適當的約束?

更新 看看下面的octavioccl的答案,我試了一下沒有任何成功。不過,我然後從UserSettings(但我離開UserId)的映射中刪除User。據我所知,一切似乎都奏效。但是,我真的很困惑這裏發生了什麼,如果這是正確的答案,或者我只是幸運的話。

回答

3

刪除數據的註釋,並用這些配置嘗試:

builder.Entity<UserSettings>() 
      .Property(b => b.UserId) 
      .HasColumnName("User_Id_Fk"); 

builder.Entity<User>() 
      .HasOne(us => us.UserSettings) 
      .WithOne(u => u.User) 
      .HasForeignKey<UserSettings>(b => b.UserId); 

EF Core documentation

在配置你需要指定依賴 實體類型的外鍵 - 注意提供的通用參數到HasForeignKey 在上面的列表中。在一對多的關係中,很顯然 具有參考導航的實體是依賴關係,並且一個 與集合是主體。但是,這不是一對一的關係 - 因此需要明確定義它。

是在quoted link給出的例子(Blog - BlogImage)幾乎是相同的什麼是你想要的目的。

如果我上面顯示的解決方案不起作用,那麼您應該檢查User_Id_Fk列是否允許null。如果是這種情況,請將FK屬性類型更改爲int?

public class UserSettings 
{ 
    public int Id { get; set; } 

    public int? UserId { get; set; } 

    public virtual User User { get; set; } 
} 
+0

感謝您的回覆。不幸的是,沒有去。我對你的答案有點困惑,用戶應該只有零個或一個UserSetting。我不瞭解你的解決方案如何實現這一點。 (這超出了我仍然收到相同錯誤的事實。)您能否提供澄清?謝謝! – JasCav

+0

添加了編輯/更新。 – JasCav

+0

我現在看到你的更新了,我認爲它的效果很好,因爲EF認爲你現在的關係是一對多而不是一對一的關係。當你在相關實體之間聲明一個導航屬性時,默認情況下EF創建一對多,我也混淆了你當前模型的工作方式,因爲如果你在'UserSettings'表中有FK列,如果EF看到一對多,集合導航屬性應該在'User'中聲明,而不是參考導航屬性。確實很迷惑,讓我再想想整個一遍,如果我找到更合理的我要讓你知道 – octavioccl