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

时间:2014-06-30 04:06:29

标签: c# sql sql-server linq entity-framework

这真让我疯狂,我无法弄清楚为什么希望有人能给我一点暗示为什么它会如此表现。我有4张桌子

这两个表中的

第一组,能够给我一个干净漂亮的T-SQL(来自this link的样本)

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; }

}

使用Above表格,我使用它 LINQ

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


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

输出继电器

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]

但是第二组

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; }

}

使用 LINQ

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

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

输出

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

问题

  1. 为什么在第二个LINQ中生成C1?
  2. 为什么在第二个LINQ中有这个行CASE WHEN([Extent2]。[intid] IS NULL)THEN CAST(NULL as int)ELSE 1 END AS [C2] - 为什么它生成这个&gt;?
  3. 为什么第二个输出太复杂了?

2 个答案:

答案 0 :(得分:1)

  1. C1列似乎与查询无关 - 它可能是自动发生的优化或保护,因此LINQ无法意外地创建无效的内容 - 或者可能是第一行不能无意中具有NULL值。

  2. 生成C2列作为对空值的保护,因为该值被归为主键(这意味着它不能为空)。由于您正在进行LEFT OUTER JOIN,因此左侧的值可能没有连接记录 - 但仍必须显示LEFT信息的有效行。

  3. 查询看起来更复杂,因为它在选择结果之前在临时表中构造此额外信息。这可能是以这种方式解决问题,因为这是它知道如何通过代码生成它的唯一方式 - 或者它可能足够聪明,知道这个查询对于查询来说稍微更优化引擎(我可能不会赌它)。

答案 1 :(得分:1)

在第一种情况下,您正在为简单导航属性执行Include (因此可以使用简单的左外连接完成,响应中的每一行将在结果中实现为实体), 在第二种情况下包含集合,因此结果中的几行应合并为单个实体及其集合属性。因此,SQL查询必须以下列方式编写: 1.将在单个实体中合并的所有行将按顺序获取 2.促进检测群体界限的过程 3.减少数据重复 在这种简单的情况下,可以消除生成的SQL的某些部分,但是当e.t.c中包含多个集合属性时,它们将用于更复杂的查询。