EF6是如何知道派生类型的?
本文关键字:类型 派生 何知道 EF6 | 更新日期: 2023-09-27 18:09:57
我使用实体框架6与每类型表继承方法。
表看起来像这样(只是一个例子):
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
型。我可以安全地强制转换它并访问派生类型的属性。
这是一个伟大的功能,我喜欢它,但我想知道它是如何工作的,以便在未来保持这个功能。它是使用enum还是在所有表中寻找具有相同ID的实体?
对于TPT策略,它确实对所有相关的表使用它是使用enum还是在所有表中寻找具有相同ID的实体?
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]
详细说明可以在EF代码优先的继承:第2部分-每个类型的表(TPT)中找到。
默认情况下,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