2016-10-02 87 views
1

我使用Entity Framework 6和Table-Per-Type繼承方法。EF6如何知道派生類型?

表如下所示(只是一個例子):

ConfigurationKeys 
    ID - int, not null, auto increment, primary 
    ConfigurationKeyType - int, not null 
    Key - varchar(50), not null 

StringConfigurationKeys 
    ID - int, not null, primary (foreign key to ConfigurationKey.ID) 
    StringValue - varchar(50), not null 

IntConfigurationKeys 
    ID - int, not null, primary (foreign key to ConfigurationKey.ID) 
    IntValue - int, not null 

和下面的類結構:

public enum ConfigurationKeyType 
{ 
    StringConfigurationKey = 0, 
    IntConfigurationKey = 1 
} 

[Table("ConfigurationKeys")] 
public class ConfigurationKey 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int ID { get; set; } 

    public ConfigurationKeyType ConfigurationKeyType { get; set; } 

    public string Key { get; set; } 
} 

[Table("StringConfigurationKeys")] 
public class StringConfigurationKey : ConfigurationKey 
{ 
    public string StringValue { get; set; } 
} 

[Table("IntConfigurationKeys")] 
public class IntConfigurationKey : ConfigurationKey 
{ 
    public int IntValue { get; set; } 
}  

沒有其它的構造和模型構建器映射製成。

現在,當我做下面的查詢:

var keys = context.ConfigurationKeys.ToArray(); 

實體框架返回派生類型的數組。
即,keys[0]可以是IntConfigurationKeykeys[1]可以是StringConfigurationKey類型。我可以安全地轉換它並訪問派生類型的屬性。
這是一個很棒的功能,我喜歡它,但我想知道它是如何工作的,以便在將來保持此功能。
它使用枚舉或它是否在所有表中查找具有相同ID的實體?

回答

1

是否使用枚舉或者它尋找一個所有表中具有相同ID的實體?

隨着TPT策略它確實使用LEFT OUTER JOIN s到所有相關表用於確定所述派生類型(和數據)。沒有鑑別器列或您的枚舉被使用。

您可以通過打開EF日誌記錄或使用query.ToString()來查看生成的SQL。因此,無論

var sql = context.ConfigurationKeys.ToString(); 

context.Database.Log = Console.WriteLine; 
var keys = context.ConfigurationKeys.ToArray(); 

會顯示這樣的事情:

SELECT 
    CASE WHEN ((NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL))) AND (NOT (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)))) THEN '0X' WHEN (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL)) THEN '0X0X' ELSE '0X1X' END AS [C1], 
    [Extent1].[ID] AS [ID], 
    [Extent1].[ConfigurationKeyType] AS [ConfigurationKeyType], 
    [Extent1].[Key] AS [Key], 
    CASE WHEN ((NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL))) AND (NOT (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)))) THEN CAST(NULL AS int) WHEN (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL)) THEN [Project1].[IntValue] END AS [C2], 
    CASE WHEN ((NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL))) AND (NOT (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL)) THEN CAST(NULL AS varchar(1)) ELSE [Project2].[StringValue] END AS [C3] 
    FROM [dbo].[ConfigurationKeys] AS [Extent1] 
    LEFT OUTER JOIN (SELECT 
     [Extent2].[ID] AS [ID], 
     [Extent2].[IntValue] AS [IntValue], 
     cast(1 as bit) AS [C1] 
     FROM [dbo].[IntConfigurationKeys] AS [Extent2]) AS [Project1] ON [Extent1].[ID] = [Project1].[ID] 
    LEFT OUTER JOIN (SELECT 
     [Extent3].[ID] AS [ID], 
     [Extent3].[StringValue] AS [StringValue], 
     cast(1 as bit) AS [C1] 
     FROM [dbo].[StringConfigurationKeys] AS [Extent3]) AS [Project2] ON [Extent1].[ID] = [Project2].[ID] 

詳細解釋可以在Inheritance with EF Code First: Part 2 – Table per Type (TPT)找到。

+0

這是對我的問題的完美和完整的答案:)謝謝。 –

0

默認情況下,EF使用Table per Hierarchy策略創建數據庫表,因此,您的類將映射到單個表,並且會有一個鑑別器列。

這就是爲什麼你看到不同的具體類型

返回想了解更多關於在EF繼承的所有數據,請點擊此鏈接https://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/implementing-inheritance-with-the-entity-framework-in-an-asp-net-mvc-application

+0

它使用Table-Per-Type策略,因爲我用'Table'屬性標記每個類,這個屬性告訴EF6每個類型到一個單獨的表。 –

+0

因此,您在數據庫中找到3個表格? –

+0

是的,正好:)當我將數據插入到表中時,它正確地創建了具有相同ID的子表中帶有自動生成的ID和派生對象的基本實體。 –