我有一個繼承層次結構設置,我先通過代碼中的TPT映射到數據庫。在大多數情況下,層次結構是一個層次,但有時它是兩個層次。我的基類看起來是這樣的:EF代碼第一多級繼承問題
public class AuditEvent
{
public int AuditEventID;
//other stuff
};
然後我有一堆看起來像這樣(具有不同名稱和性質)其他類:
public class PageRequest : AuditEvent
{
/// <summary>
/// Page Request Id (Primary Key)
/// </summary>
public Int64 PageRequestID { get; set; }
/// <summary>
/// Screen (page) being requested
/// </summary>
public string Screen { get; set; }
/// <summary>
/// Http Method
/// </summary>
public string HttpMethod { get; set; }
/// <summary>
/// Confirmation Logs linked to this page request
/// </summary>
public virtual List<ConfirmationLog> ConfirmationLogs { get; set; }
}
這個特定的類(PageRequest)是父一個叫ConfirmationLog其他類,它看起來像這樣:
/// <summary>
/// Object used to log confirmations to the auditing database
/// </summary>
public class ConfirmationLog : PageRequest
{
/// <summary>
/// Confirmation ID
/// </summary>
public long ConfirmationID { get; set; }
/// <summary>
/// Confirmation number
/// </summary>
public string ConfirmationNum { get; set; }
/// <summary>
/// Web action ID (automated alert or transaciton confirmation number)
/// </summary>
public int WebActionID { get; set; }
}
我使用的配置類和流暢API配置映射,像這樣:
/// <summary>
/// Configuration class for PageRequest
/// </summary>
public class PageRequestConfiguration : EntityTypeConfiguration<PageRequest>
{
/// <summary>
/// Default constructor
/// </summary>
public PageRequestConfiguration()
{
//Table
ToTable("PageRequests");
//primary key
HasKey(a => a.PageRequestID);
//Properties
Property(a => a.PageRequestID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(a => a.Screen).IsRequired().HasMaxLength(100);
Property(a => a.HttpMethod).IsRequired().HasMaxLength(10);
}
}
/// <summary>
/// Confirmation Log configuration class. Configures the confirmation log class for the db model
/// </summary>
public class ConfirmationLogConfiguration : EntityTypeConfiguration<ConfirmationLog>
{
/// <summary>
/// Default constructor
/// </summary>
public ConfirmationLogConfiguration()
{
//Map to Table
ToTable("ConfirmationLogs");
//Primary Key
HasKey(a => a.ConfirmationID);
//required fields
Property(a => a.ConfirmationID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(a => a.PageRequestID).IsRequired();
Property(a => a.ConfirmationNum).IsRequired().HasMaxLength(12);
Property(a => a.WebActionID).IsRequired();
}
}
然後,我根據這個層次創建一個相當大的LINQ查詢。我會放過這個查詢,因爲它大概是由10個步驟組成的,我不認爲這是我的問題的根源。問題是,當我運行查詢時,出於某種原因生成的SQL認爲列ConfirmationLogs表(孫表)上存在AuditEventID列(基類的主鍵)。 ConfirmationLogs表有一個外鍵給它的父表(PageRequests),然後它的外鍵就是它的父表(AuditEvents)。
我的問題是,我是否設置了錯誤的等級? 「孫子」表是否需要它的父母和祖父母的外鍵才能起作用? (如果它確實發現不幸)。
我認爲繼承關係會拋出一些東西,因爲如果我不使用HasRequired()/ WithMany()將PageRequests的子項作爲PageRequests的子項並配置爲PageRequests,那麼事情就可以正常工作。
任何幫助,將不勝感激。
更新
於是,經過進一步調查,我認爲有一個與我試圖使用繼承方式的一個普遍問題。我應該注意到,我試圖將代碼先映射到現有數據庫。在數據庫中,我有我的AuditEvent表和一堆像「PageRequest」這樣的「子」表。頁面請求具有稱爲PageRequestID的自己的主鍵以及名爲AuditEventID的外鍵。其他子表的設置方式相同。在我的PageRequest的配置類(上面列出)中,我試圖通過使用HasKey函數來表示該PageRequestID是主鍵,並假定EF將通過約定和繼承知道外鍵AuditEventID。我還應該注意到,我可以使用該模型寫入數據庫。如果我想寫一個PageRequest,我創建PageRequest對象,填充由PageRequest和AuditEvent基類定義的所有必填字段,並通過上下文進行保存。 EF創建AuditEvent記錄,並將FK的pageRequest記錄返回給AuditEvent。
是什麼讓我覺得我沒有使用繼承權是我允許EF爲我創建我的數據庫,使用我創建的模型和映射。對於PageRequest表(和所有其他子表),EF實際上創建了一個名爲AuditEventID的主鍵(即使我的配置告訴它做其他事情)。該鍵也被標記爲外鍵,並且我想要創建的列作爲主鍵(本示例中爲PageRequestID)僅被配置爲必需(不可爲空)。所以看起來,EF從我的BASE類中獲取主鍵,並將它用作子類中的主鍵和外鍵,就像AuditEventID的概念在父表和子表之間傳播一樣。有沒有辦法改變這種行爲?
我很困惑。我期望列AuditEventID只是因爲它是ConfirmationLogs類的一個屬性。您是否嘗試過使用忽略(a => a.AuditEventID)語句來顯式刪除該字段? – bryanjonker
AuditEventID是基類AuditEvent的屬性,而不是ConfirmationLogs。確認日誌與AuditEvent沒有直接關係,AuditEvent是「祖父母」。 –
忽略()不好意思。 –