繁体   English   中英

在TPT继承中查询基类时,为什么实体框架包含带有外部联接的派生类

[英]Why does entity framework include derived classes with outer join when querying against the base class in TPT inheritance

我正在使用具有TPT(每个类型的表)继承的实体框架6。

我有这节课

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

使用包含时查询更难更改

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

是否有解决此问题的解决方法?

当我想要的只是人员类时,实体框架添加所有这些外部联接的原因是什么?

EF希望了解实体的确切类型( PersonCustomerIndividualCustomer等),以便能够创建正确的实例。 因此,它只能从连接层次结构的所有表中获取类型信息(请参阅case语句)。

是否有解决此问题的解决方法?

一种可能的替代方法是应用-与您一样仅从基类中查询所需的属性。 另一种可能的选择-使用带有区分符列的按层次结构表。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM