我使用Entity Framework 6和Table-Per-Type继承方法。
表格看起来像这样(只是一个例子):
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]
可以是IntConfigurationKey
,keys[1]
可以是StringConfigurationKey
类型。我可以安全地转换它并访问派生类型的属性
这是一个很棒的功能,我喜欢它,但我想知道它是如何工作的,以便将来保持这种功能
它是使用枚举还是在所有表中查找具有相同ID的实体?
答案 0 :(得分:1)
它是使用枚举还是在所有表中查找具有相同ID的实体?
使用TPT策略,它会对所有相关表使用LEFT OUTER JOIN
来确定派生类型(和数据)。没有使用鉴别器列或您的枚举。
您可以通过打开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)中找到。
答案 1 :(得分:0)
默认情况下,EF使用Table per Hierarchy策略来创建数据库表,因此,您的类将映射到单个表,并且将有一个鉴别器列。
这就是您看到从不同具体类型返回的所有数据的原因