我使用实体框架6和TPT(Table-per-type)继承。
我有这个课程
public class Person
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public class Customer : Person
{
public string BillingAddress { get; set; }
}
public class IndividualCustomer : Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime Birthday { get; set; }
}
public class CorporateCustomer : Customer
{
public string ContactPerson { get; set; }
public string CorporateTaxNo { get; set; }
}
public class SalesInvoice
{
public Guid Id { get; set; }
public Guid CustomerId { get; set; }
public Customer Customer { get; set; }
}
当我执行此查询时
var people = ctx.People.ToList();
实体框架生成此查询
SELECT
CASE WHEN (( NOT (([Project4].[C1] = 1) AND ([Project4].[C1] IS NOT NULL))) AND ( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL)))) THEN '0X' WHEN (([Project4].[C3] = 1) AND ([Project4].[C3] IS NOT NULL)) THEN '0X0X0X' WHEN (([Project4].[C1] = 1) AND ([Project4].[C1] IS NOT NULL) AND ( NOT (([Project4].[C2] = 1) AND ([Project4].[C2] IS NOT NULL))) AND ( NOT (([Project4].[C3] = 1) AND ([Project4].[C3] IS NOT NULL)))) THEN '0X0X' WHEN (([Project4].[C2] = 1) AND ([Project4].[C2] IS NOT NULL)) THEN '0X0X1X' ELSE '0X1X' END AS [C1],
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
CASE WHEN (( NOT (([Project4].[C1] = 1) AND ([Project4].[C1] IS NOT NULL))) AND ( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project4].[C3] = 1) AND ([Project4].[C3] IS NOT NULL)) THEN [Project4].[BillingAddress] WHEN (([Project4].[C1] = 1) AND ([Project4].[C1] IS NOT NULL) AND ( NOT (([Project4].[C2] = 1) AND ([Project4].[C2] IS NOT NULL))) AND ( NOT (([Project4].[C3] = 1) AND ([Project4].[C3] IS NOT NULL)))) THEN [Project4].[BillingAddress] WHEN (([Project4].[C2] = 1) AND ([Project4].[C2] IS NOT NULL)) THEN [Project4].[BillingAddress] END AS [C2],
CASE WHEN (( NOT (([Project4].[C1] = 1) AND ([Project4].[C1] IS NOT NULL))) AND ( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project4].[C3] = 1) AND ([Project4].[C3] IS NOT NULL)) THEN [Project4].[ContactPerson] WHEN (([Project4].[C1] = 1) AND ([Project4].[C1] IS NOT NULL) AND ( NOT (([Project4].[C2] = 1) AND ([Project4].[C2] IS NOT NULL))) AND ( NOT (([Project4].[C3] = 1) AND ([Project4].[C3] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project4].[C2] = 1) AND ([Project4].[C2] IS NOT NULL)) THEN CAST(NULL AS varchar(1)) END AS [C3],
CASE WHEN (( NOT (([Project4].[C1] = 1) AND ([Project4].[C1] IS NOT NULL))) AND ( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project4].[C3] = 1) AND ([Project4].[C3] IS NOT NULL)) THEN [Project4].[CorporateTaxNo] WHEN (([Project4].[C1] = 1) AND ([Project4].[C1] IS NOT NULL) AND ( NOT (([Project4].[C2] = 1) AND ([Project4].[C2] IS NOT NULL))) AND ( NOT (([Project4].[C3] = 1) AND ([Project4].[C3] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project4].[C2] = 1) AND ([Project4].[C2] IS NOT NULL)) THEN CAST(NULL AS varchar(1)) END AS [C4],
CASE WHEN (( NOT (([Project4].[C1] = 1) AND ([Project4].[C1] IS NOT NULL))) AND ( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project4].[C3] = 1) AND ([Project4].[C3] IS NOT NULL)) THEN CAST(NULL AS varchar(1)) WHEN (([Project4].[C1] = 1) AND ([Project4].[C1] IS NOT NULL) AND ( NOT (([Project4].[C2] = 1) AND ([Project4].[C2] IS NOT NULL))) AND ( NOT (([Project4].[C3] = 1) AND ([Project4].[C3] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project4].[C2] = 1) AND ([Project4].[C2] IS NOT NULL)) THEN [Project4].[FirstName] END AS [C5],
CASE WHEN (( NOT (([Project4].[C1] = 1) AND ([Project4].[C1] IS NOT NULL))) AND ( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project4].[C3] = 1) AND ([Project4].[C3] IS NOT NULL)) THEN CAST(NULL AS varchar(1)) WHEN (([Project4].[C1] = 1) AND ([Project4].[C1] IS NOT NULL) AND ( NOT (([Project4].[C2] = 1) AND ([Project4].[C2] IS NOT NULL))) AND ( NOT (([Project4].[C3] = 1) AND ([Project4].[C3] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project4].[C2] = 1) AND ([Project4].[C2] IS NOT NULL)) THEN [Project4].[LastName] END AS [C6],
CASE WHEN (( NOT (([Project4].[C1] = 1) AND ([Project4].[C1] IS NOT NULL))) AND ( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL)))) THEN CAST(NULL AS datetime2) WHEN (([Project4].[C3] = 1) AND ([Project4].[C3] IS NOT NULL)) THEN CAST(NULL AS datetime2) WHEN (([Project4].[C1] = 1) AND ([Project4].[C1] IS NOT NULL) AND ( NOT (([Project4].[C2] = 1) AND ([Project4].[C2] IS NOT NULL))) AND ( NOT (([Project4].[C3] = 1) AND ([Project4].[C3] IS NOT NULL)))) THEN CAST(NULL AS datetime2) WHEN (([Project4].[C2] = 1) AND ([Project4].[C2] IS NOT NULL)) THEN [Project4].[Birthday] END AS [C7],
CASE WHEN (( NOT (([Project4].[C1] = 1) AND ([Project4].[C1] IS NOT NULL))) AND ( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project4].[C3] = 1) AND ([Project4].[C3] IS NOT NULL)) THEN CAST(NULL AS varchar(1)) WHEN (([Project4].[C1] = 1) AND ([Project4].[C1] IS NOT NULL) AND ( NOT (([Project4].[C2] = 1) AND ([Project4].[C2] IS NOT NULL))) AND ( NOT (([Project4].[C3] = 1) AND ([Project4].[C3] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project4].[C2] = 1) AND ([Project4].[C2] IS NOT NULL)) THEN CAST(NULL AS varchar(1)) ELSE [Project1].[Address] END AS [C8]
FROM [dbo].[Person] AS [Extent1]
LEFT OUTER JOIN (SELECT
[Extent2].[Id] AS [Id],
[Extent2].[Address] AS [Address],
cast(1 as bit) AS [C1]
FROM [dbo].[Vendor] AS [Extent2] ) AS [Project1] ON [Extent1].[Id] = [Project1].[Id]
LEFT OUTER JOIN (SELECT
[Extent3].[Id] AS [Id],
[Extent3].[BillingAddress] AS [BillingAddress],
cast(1 as bit) AS [C1],
[Project2].[ContactPerson] AS [ContactPerson],
[Project2].[CorporateTaxNo] AS [CorporateTaxNo],
[Project3].[FirstName] AS [FirstName],
[Project3].[LastName] AS [LastName],
[Project3].[Birthday] AS [Birthday],
CASE WHEN (([Project3].[C1] = 1) AND ([Project3].[C1] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Project3].[C1] = 1) AND ([Project3].[C1] IS NOT NULL))) THEN cast(0 as bit) END AS [C2],
CASE WHEN (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL))) THEN cast(0 as bit) END AS [C3]
FROM [dbo].[Customer] AS [Extent3]
LEFT OUTER JOIN (SELECT
[Extent4].[Id] AS [Id],
[Extent4].[ContactPerson] AS [ContactPerson],
[Extent4].[CorporateTaxNo] AS [CorporateTaxNo],
cast(1 as bit) AS [C1]
FROM [dbo].[CorporateCustomer] AS [Extent4] ) AS [Project2] ON [Extent3].[Id] = [Project2].[Id]
LEFT OUTER JOIN (SELECT
[Extent5].[Id] AS [Id],
[Extent5].[FirstName] AS [FirstName],
[Extent5].[LastName] AS [LastName],
[Extent5].[Birthday] AS [Birthday],
cast(1 as bit) AS [C1]
FROM [dbo].[IndividualCustomer] AS [Extent5] ) AS [Project3] ON [Extent3].[Id] = [Project3].[Id] ) AS [Project4] ON [Extent1].[Id] = [Project4].[Id]
go
当我想要的是实体框架时,实体框架添加所有外部联接的原因是什么。
但是,如果我指定要返回的字段,实体框架会返回更好的查询
var people = ctx.People.Select(x => new {x.Id, x.Name}).ToList();
返回
SELECT
1 AS [C1],
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name]
FROM [dbo].[Person] AS [Extent1]
go
使用include
时,查询更难以改变var invoices = ctx.SalesInvoices.Include("Customer").ToList();
返回
SELECT
1 AS [C1],
[Extent1].[Id] AS [Id],
[Extent1].[CustomerId] AS [CustomerId],
[Extent1].[CustomerId2] AS [CustomerId2],
CASE WHEN ([Join3].[Id1] IS NULL) THEN CAST(NULL AS varchar(1)) WHEN (((CASE WHEN (([Join3].[C11] = 1) AND ([Join3].[C11] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Join3].[C11] = 1) AND ([Join3].[C11] IS NOT NULL))) THEN cast(0 as bit) END) <> 1) AND ((CASE WHEN (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL))) THEN cast(0 as bit) END) <> 1)) THEN '2X0X' WHEN ((CASE WHEN (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL))) THEN cast(0 as bit) END) = 1) THEN '2X0X0X' ELSE '2X0X1X' END AS [C2],
[Join3].[Id1] AS [Id1],
[Join3].[Name] AS [Name],
[Join3].[BillingAddress] AS [BillingAddress],
CASE WHEN ([Join3].[Id1] IS NULL) THEN CAST(NULL AS varchar(1)) WHEN (((CASE WHEN (([Join3].[C11] = 1) AND ([Join3].[C11] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Join3].[C11] = 1) AND ([Join3].[C11] IS NOT NULL))) THEN cast(0 as bit) END) <> 1) AND ((CASE WHEN (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL))) THEN cast(0 as bit) END) <> 1)) THEN CAST(NULL AS varchar(1)) WHEN ((CASE WHEN (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL))) THEN cast(0 as bit) END) = 1) THEN [Join3].[ContactPerson] END AS [C3],
CASE WHEN ([Join3].[Id1] IS NULL) THEN CAST(NULL AS varchar(1)) WHEN (((CASE WHEN (([Join3].[C11] = 1) AND ([Join3].[C11] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Join3].[C11] = 1) AND ([Join3].[C11] IS NOT NULL))) THEN cast(0 as bit) END) <> 1) AND ((CASE WHEN (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL))) THEN cast(0 as bit) END) <> 1)) THEN CAST(NULL AS varchar(1)) WHEN ((CASE WHEN (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL))) THEN cast(0 as bit) END) = 1) THEN [Join3].[CorporateTaxNo] END AS [C4],
CASE WHEN ([Join3].[Id1] IS NULL) THEN CAST(NULL AS varchar(1)) WHEN (((CASE WHEN (([Join3].[C11] = 1) AND ([Join3].[C11] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Join3].[C11] = 1) AND ([Join3].[C11] IS NOT NULL))) THEN cast(0 as bit) END) <> 1) AND ((CASE WHEN (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL))) THEN cast(0 as bit) END) <> 1)) THEN CAST(NULL AS varchar(1)) WHEN ((CASE WHEN (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL))) THEN cast(0 as bit) END) = 1) THEN CAST(NULL AS varchar(1)) ELSE [Join3].[FirstName] END AS [C5],
CASE WHEN ([Join3].[Id1] IS NULL) THEN CAST(NULL AS varchar(1)) WHEN (((CASE WHEN (([Join3].[C11] = 1) AND ([Join3].[C11] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Join3].[C11] = 1) AND ([Join3].[C11] IS NOT NULL))) THEN cast(0 as bit) END) <> 1) AND ((CASE WHEN (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL))) THEN cast(0 as bit) END) <> 1)) THEN CAST(NULL AS varchar(1)) WHEN ((CASE WHEN (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL))) THEN cast(0 as bit) END) = 1) THEN CAST(NULL AS varchar(1)) ELSE [Join3].[LastName] END AS [C6],
CASE WHEN ([Join3].[Id1] IS NULL) THEN CAST(NULL AS datetime2) WHEN (((CASE WHEN (([Join3].[C11] = 1) AND ([Join3].[C11] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Join3].[C11] = 1) AND ([Join3].[C11] IS NOT NULL))) THEN cast(0 as bit) END) <> 1) AND ((CASE WHEN (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL))) THEN cast(0 as bit) END) <> 1)) THEN CAST(NULL AS datetime2) WHEN ((CASE WHEN (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL)) THEN cast(1 as bit) WHEN ( NOT (([Join3].[C12] = 1) AND ([Join3].[C12] IS NOT NULL))) THEN cast(0 as bit) END) = 1) THEN CAST(NULL AS datetime2) ELSE [Join3].[Birthday] END AS [C7]
FROM [dbo].[SalesInvoice] AS [Extent1]
LEFT OUTER JOIN (SELECT [Extent2].[Id] AS [Id1], [Extent2].[BillingAddress] AS [BillingAddress], [Project1].[ContactPerson] AS [ContactPerson], [Project1].[CorporateTaxNo] AS [CorporateTaxNo], [Project1].[C1] AS [C12], [Project2].[FirstName] AS [FirstName], [Project2].[LastName] AS [LastName], [Project2].[Birthday] AS [Birthday], [Project2].[C1] AS [C11], [Extent5].[Name] AS [Name]
FROM [dbo].[Customer] AS [Extent2]
LEFT OUTER JOIN (SELECT
[Extent3].[Id] AS [Id],
[Extent3].[ContactPerson] AS [ContactPerson],
[Extent3].[CorporateTaxNo] AS [CorporateTaxNo],
cast(1 as bit) AS [C1]
FROM [dbo].[CorporateCustomer] AS [Extent3] ) AS [Project1] ON [Extent2].[Id] = [Project1].[Id]
LEFT OUTER JOIN (SELECT
[Extent4].[Id] AS [Id],
[Extent4].[FirstName] AS [FirstName],
[Extent4].[LastName] AS [LastName],
[Extent4].[Birthday] AS [Birthday],
cast(1 as bit) AS [C1]
FROM [dbo].[IndividualCustomer] AS [Extent4] ) AS [Project2] ON [Extent2].[Id] = [Project2].[Id]
INNER JOIN [dbo].[Person] AS [Extent5] ON [Extent2].[Id] = [Extent5].[Id] ) AS [Join3] ON [Extent1].[CustomerId] = [Join3].[Id1]
go
有解决方法吗?
答案 0 :(得分:0)
当我想要的是实体框架时,实体框架添加所有外部联接的原因是什么。
EF希望知道实体的确切类型(Person
,Customer
,IndividualCustomer
等),以便能够创建正确的实例。因此,它只能从加入层次结构的所有表中获取类型信息(参见case语句)。
有解决方法吗?
可能的替代方法之一是应用 - 只查询基类中所需的属性,就像您一样。另一种可能的选择 - 使用带有鉴别器列的每个层次表。