2013-07-19 106 views
0

我有一個EF數據模型,它表示具有報告部分的分層樹的報告。每個ReportSection實體都包含一個零個或多個子ReportSection的集合。每個Report實體都包含一個ReportSection實體,用作ReportSections的樹的根。具有下列導航屬性EF代碼優先可選1對1關係

我的數據模型:

public class Report 
{ 
    // Primary key 
    public int Id { get; set; } 

    // A Report has one root ReportSection 
    [ForeignKey("RootReportSection")] 
    public int ReportSectionId { get; set; } 
    public virtual ReportSection RootReportSection { get; set; } 
} 

public class ReportSection 
{ 
    // Primary key 
    public int Id { get; set; } 

    // Optional self-reference to the parent ReportSection 
    [ForeignKey("ParentReportSection")] 
    public int? ParentReportSectionId { get; set; } 
    public virtual ReportSection ParentReportSection { get; set; } 

    // Optional foreign key to the parent Report 
    [ForeignKey("ParentReport")] 
    public int? ReportId { get; set; } 
    public virtual Report ParentReport { get; set; } 

    // Child ReportSections contained in this ReportSection 
    public virtual ICollection<ReportSection> ReportSections { get; set; } 
} 

一切工作正常,如果我忽略從報告實體ReportSectionIdRootReportSection導航譁衆取寵。但是,正如上述編碼,嘗試添加遷移得到一個錯誤:

Because the Dependent Role properties are not the key properties, 
the upper bound of the multiplicity of the Dependent Role must be '*'. 

有點挖後,我現在明白了,EF顯然是要我用我的ReportSections實體的主鍵的外鍵我的報告實體。但是,在我的場景中,只有ReportSection實體的分層樹中的頂級ReportSection參與與Report實體的關係。 ReportSection實體的其餘部分相互關聯,其主鍵獨立於任何報表主鍵。

有沒有辦法讓這個工作?具體來說,Report實體是否有辦法「包含」頂級ReportSection實體,哪個ReportSection實體具有自己的自引用ReportSection實體的集合?

回答

1

顯然ReportSection是在關係UND Report從屬(因爲必須Report引用現有RootReportSection因爲Report.ReportSectionId不可爲空)的主體。在這種情況下,存在ReportSection很可能沒有相關的Report。您的所有子女ReportSection將不會有Report

但是,只有在Report中的密鑰不是自動生成的,因爲密鑰必須與相關(和現有的)RootReportSection的密鑰相同。所以,你可以嘗試像這樣型號:

public class Report 
{ 
    [DatabaseGenerated(DatabaseGeneratedOption.None)] 
    [ForeignKey("RootReportSection")] 
    public int Id { get; set; } 

    public virtual ReportSection RootReportSection { get; set; } 
} 

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

    // Optional self-reference to the parent ReportSection 
    [ForeignKey("ParentReportSection")] 
    public int? ParentReportSectionId { get; set; } 
    public virtual ReportSection ParentReportSection { get; set; } 

    // Optional foreign key to the parent Report 
    public virtual Report ParentReport { get; set; } 

    // Child ReportSections contained in this ReportSection 
    public virtual ICollection<ReportSection> ReportSections { get; set; } 
} 

(這有可能是[DatabaseGenerated(DatabaseGeneratedOption.None)]是多餘的,因爲EF明白,不能在這一個一對一的關係生成密鑰數據庫我不是100%確保雖然)。

這樣一來,一個具有共享主鍵關係的缺點是,你不能改變ReportRootReportSection之間的關係,即你不能有Report指任何其他部分比一個具有相同的主鍵。

如果這不適用於您,則必須將關係建模爲一對多,因爲EF不支持使用單獨外鍵的一對一關係。要麼刪除部分共...

[ForeignKey("ParentReport")] 
public int? ReportId { get; set; } 
public virtual Report ParentReport { get; set; } 

...如果你不需要從區域導航到該報告,或集合替換:

public virtual ICollection<Report> ParentReports { get; set; } 

你將不得不確保在業務邏輯中只有一個報告被添加到這個集合中,以模擬一對一的關係。在數據庫中,您可以在Report.ReportSectionId上添加一個唯一約束,以在數據庫級別具有數據完整性。但是EF不理解這個約束,並且仍然允許向該集合添加多個項目。但是,如果您嘗試保存它,則會從數據庫中獲得唯一的密鑰違例例外。