简体   繁体   English

为什么使用几乎相同的表结构生成不同的T-SQL

[英]Why different T-SQL generated with almost same table structure

This really make me crazy and i cant figure out why hope someone could give me a little hint why it's behave so. 这真的让我发疯,我不知道为什么希望有人能给我一点提示,为什么它会如此。 I have 4 tables 我有4张桌子

1st group of these 2 tables and is able to give me a clean and nice T-SQL (sample from this link ) 这2个表的第1组 ,能够给我一个干净漂亮的T-SQL(来自此链接的示例)

public class Standard
{
    public Standard()
    {
        Students = new List<Student>();
    }
    public int StandardId { get; set; }
    public string StandardName { get; set; }
    public string Description { get; set; }

    public virtual ICollection<Student> Students { get; set; }
}

public class Student
{
    public Student() { }

    public int StudentId { get; set; } 
    public string StudentName { get; set; } 

    public virtual Standard Standard { get; set; }

}

With Above tables and i use this LINQ 与上面的表,我用这个LINQ

List<Student> student = context.student.ToList();


var r = from ord in context.student.Include("standard") 
        select ord;

Ouput 乌普特

SELECT 
[Extent1].[StudentId] AS [StudentId], 
[Extent1].[StudentName] AS [StudentName], 
[Extent2].[StandardId] AS [StandardId], 
[Extent2].[StandardName] AS [StandardName], 
[Extent2].[Description] AS [Description]
FROM  [dbo].[Students] AS [Extent1]
LEFT OUTER JOIN [dbo].[Standards] AS [Extent2] ON [Extent1].[Standard_StandardId] = [Extent2].[StandardId]

But with 2nd Group 但是第二组

public partial class Cust_ProfileTbl
{
    public Cust_ProfileTbl()
    {
        balance = new List<BP_BalanceTbl>();
    }
    [Key]
    public virtual long bintAccountNo { get; set; }
    public string varCardNo { get; set; }


    public virtual ICollection<BP_BalanceTbl> balance { get; set; }


}


public class BP_BalanceTbl
{
    public BP_BalanceTbl() { }
    public virtual long bintAccountNo { get; set; }
    [Key]
    public int intid { get; set; }
    public virtual Cust_ProfileTbl profile { get; set; }

}

with this LINQ 用这个LINQ

List<Cust_ProfileTbl> profile = context.profile.ToList();

var rs = from ord in context.profile.Include("balance")
        select ord;

Output 输出量

SELECT 
[Project1].[C1] AS [C1], 
[Project1].[bintAccountNo] AS [bintAccountNo], 
[Project1].[varCardNo] AS [varCardNo], 
[Project1].[C2] AS [C2], 
[Project1].[intid] AS [intid], 
[Project1].[bintAccountNo1] AS [bintAccountNo1]
FROM ( SELECT 
    [Extent1].[bintAccountNo] AS [bintAccountNo], 
    [Extent1].[varCardNo] AS [varCardNo], 
    1 AS [C1],      --Why it generate this>?
    [Extent2].[intid] AS [intid], 
    [Extent2].[bintAccountNo] AS [bintAccountNo1], 
    CASE WHEN ([Extent2].[intid] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2] --Why it generate this>?
    FROM  [dbo].[Cust_ProfileTbl] AS [Extent1]
    LEFT OUTER JOIN [dbo].[BP_BalanceTbl] AS [Extent2] ON [Extent1].[bintAccountNo] = [Extent2].[bintAccountNo]
)  AS [Project1]
ORDER BY [Project1].[bintAccountNo] ASC, [Project1].[C2] ASC

Questions 问题

  1. Why in 2nd LINQ it's generate C1? 为什么在第二个LINQ中它生成C1?
  2. Why in 2nd LINQ have this line CASE WHEN ([Extent2].[intid] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2] --Why it generate this>? 为什么在第二个LINQ中,这行是CASE WHEN([[Extent2]。[intid]是NULL)然后CAST(NULL AS int)ELSE 1 END AS [C2]-为什么它生成此>?
  3. Why the 2nd output is so complex? 为什么第二个输出如此复杂?
  1. The C1 column doesn't appear to be relevant to the query - it might be an optimisation or protection that happens automatically so that LINQ can't accidentally create something invalid - or perhaps so that the first row can't inadvertently have NULL values. C1列似乎与查询无关-它可能是自动进行的优化或保护,因此LINQ不会意外创建无效的内容-或也许第一行不会无意中包含NULL值。

  2. The C2 column is generated as a protection against a null value since the value is attributed as a Primary Key (which means that it cannot be empty). 生成C2列是为了防止空值,因为该值被归为主键(这意味着它不能为空)。 Since you are doing a LEFT OUTER JOIN, the values on the left may not have joining records - but must still display a valid row for the LEFT information. 由于您正在执行LEFT OUTER JOIN,因此左侧的值可能没有连接记录-但仍必须显示LEFT信息的有效行。

  3. The query only looks more complex because it's constructing this extra information in a temporary table before selecting the results. 该查询看起来仅更为复杂,因为它是在选择结果之前在临时表中构造此额外信息。 It might be laying the query out in this way just because that's the only way it knows how to generate it through code - or maybe it's smart enough to know that this query is slightly more optimal for a query engine (I probably wouldn't bet on that). 它可能以这种方式布置查询,因为那是它知道如何通过代码生成查询的唯一方式-也许它足够聪明,知道此查询对于查询引擎而言稍为最佳(我可能不会打赌上)。

In first case you are doing Include for simple navigation property (thus it can be done with simple left outer join and each row in response will be materialized as entity in result), in second case collection is included thus several rows from result should be merged into single entity and its collection property. 在第一种情况下,您正在为简单的导航属性执行Include(因此可以通过简单的左外部联接来完成,并且响应中的每一行都将在结果中具体化为实体),在第二种情况下,将包含collection,因此应合并来自结果的几行成单个实体及其集合属性。 Thus SQL query have to be written in following way that: 1. All rows to be merged in single entity will be fetched sequentially 2. Facilitate process of detection group bounds 3. Reduce data duplication Some parts of generated SQL can be eliminated in this simple case, but they are used in more complex queries when several collection properties are included etc 因此,必须以以下方式编写SQL查询:1.将按顺序提取要在单个实体中合并的所有行2.简化检测组范围的过程3.减少数据重复用这种简单的方法可以消除生成的SQL的某些部分情况,但是当包含多个集合属性时,它们可用于更复杂的查询中

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

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