簡體   English   中英

一對一映射問題

[英]One-To-One Mapping issue

我的SQL理解是相當基礎的,我來自NHibernate的世界,所以我對這個問題感到很困惑......

我有兩節課:

public class UserProfile
{
    public UserProfile() { }

    [Key]
    public int UserId { get; set; }
    public string UserName { get; set; }
    public SerialNumber Serial { get; set; }
    // Other properties
}

public class SerialNumber
{
    public SerialNumber() 
    {
        // My code that creates a unique Code
    }

    [Key]
    public string Code { get; set; }
    public UserProfile User { get; set; }

    // Other Properties
}

我有這個

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // Other modelBuilder stuff

    modelBuilder.Entity<UserProfile>()
        .HasOptional(s => s.Serial)
        .WithRequired(u => u.User);
}

運行Add-Migration我得到了這個:

public override void Up()
{
    DropForeignKey("dbo.UserProfile", "Serial_Code", "dbo.SerialNumbers");
    DropIndex("dbo.UserProfile", new[] { "Serial_Code" });
    RenameColumn(table: "dbo.SerialNumbers", name: "Serial_Code", newName: "User_UserId");
    AddForeignKey("dbo.SerialNumbers", "User_UserId", "dbo.UserProfile", "UserId");
    CreateIndex("dbo.SerialNumbers", "User_UserId");
}

public override void Down()
{
    // Inverse of above
}

運行Update-Database我收到一個錯誤: "Either the parameter @objname is ambiguous or the claimed @objtype (COLUMN) is wrong."

我可以通過Add-Migration生成的代碼告訴我出錯了,因為我的db表甚至沒有名為"Serial_Code"

我需要Code作為我的Key因為EntityFramework沒有選項強制列為Unique除非使其成為鍵。

如何將Serial作為UserProfile的可選屬性,並將SerialNumber User添加到UserProfile時自動設置?

默認情況下,在一對一關系中,Entity Framework要求依賴項上的外鍵也是主鍵。 這可能是因為實體框架僅對主鍵設置了唯一約束(或者說,由於它是主鍵,因此存在唯一約束)。 在數據庫的級別上,一對一不映射到關系的兩側,即在兩個表上都沒有創建外鍵。 當您考慮參照完整性如何工作時,這是有道理的:如果關系的一方被刪除,則會導致另一方的數據庫分離,導致一種無限循環。

因此,外鍵被添加到依賴項,在這種情況下,就像你在這里一樣,這就是具有所需導航屬性的結尾:你的SerialNumber模型。 這意味着要真正創建一對一而不是一對多, SerialNumber上的密鑰需要是User_UserId (自動生成的外鍵列,因為您沒有手動指定外鍵屬性) )。 要以這種方式進行設置,您的模型將如下所示:

public class UserProfile
{
    [Key]
    public int UserId { get; set; }

    public SerialNumber Serial { get; set; }

    ...
}

public class SerialNumber
{
    [Key]
    [ForeignKey("User")]
    public int UserId { get; set; }

    public UserProfile User { get; set; }

    ...
}

或者使用Fluent API:

modelBuilder.Entity<SerialNumber>()
    .HasRequired(m => m.User)
    .WithOptional(m => m.Serial);

(您需要省略[Key]數據注釋,以便EF可以創建外鍵,它們是表的主鍵。)

但是,這使您在Code屬性上沒有唯一約束。 您當然可以在表上手動設置此約束,或者如果您不使用自動遷移,則可以更改遷移以創建約束:

CreateIndex("dbo.SerialNumbers", "Code", unique: true);

這里的問題是實體框架不會為您處理唯一的驗證。 因此,您需要在代碼中手動維護完整性(即,嘗試使用您要保存的Code查找SerialNumber ,並且只有在您從查詢中得不到任何內容時才保存它)。

我知道,這是一種痛苦,但就目前而言,這就是你所能做的一切。 希望EF能夠最終解決未來版本中的獨特性問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM