2016-10-02 3 views
1

Я использую Entity Framework 6 с подходом наследования на основе типа.Как 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(); 

Entity Framework возвращает массив производных типов.
I.e., keys[0] может быть IntConfigurationKey и keys[1] может быть типа StringConfigurationKey. Я могу безопасно использовать его и получить доступ к свойствам производных типов.
Это отличная функция, и мне она нравится, но я хотел бы знать, как она работает, чтобы поддерживать эту функциональность в будущем.
Использует ли он перечисление или ищет объект с одинаковым идентификатором во всех таблицах?

ответ

1

Использует ли это перечисление или это искать объект с одинаковым идентификатором во всех таблицах?

С стратегией TPT это использовать LEFT OUTER JOIN с для всех связанных таблиц для определения производного типа (и данные). Нет столбца дискриминатора или вашего перечисления.

Это можно увидеть, если посмотреть на сгенерированный SQL, включив ведение журнала EF или используя query.ToString(). Так как

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 использует стратегию «Таблица для каждой иерархии» для создания таблиц базы данных, поэтому ваши классы будут сопоставлены с одной таблицей, и будет столбец дискриминатора.

Вот почему вы видите все данные, возвращаемые из различных конкретных типов

Чтобы узнать больше о наследстве в 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, потому что я отмечил каждый класс атрибутом «Таблица», который сообщает EF6, что каждый тип для отдельной таблицы. –

+0

Итак, вы нашли 3 таблицы в базе данных? –

+0

Да, точно :) Когда я вставляю данные в таблицы, он правильно создает базовый объект с автоматически сгенерированным идентификатором и производным объектом в дочерней таблице с тем же идентификатором. –

Смежные вопросы