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

1st group of these 2 tables and is able to give me a clean and nice T-SQL (sample from 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; }

}

With Above tables and i use this 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

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?
  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>?
  3. Why the 2nd output is so complex?

Answers


  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.

  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). 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.

  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. 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 e.t.c.


Need Your Help

CriticalSection: what are performance issues on multicore CPUs?

x86 arm critical-section

I'm not concerned about the case when multiple threads try to acquire a CS.

When HttpModule Init method runs in ASP.NET Integrated mode?

c# asp.net nhibernate iis-7 httpmodule

I've written an HttpModule that is an NHibernate Session Provider. It simply opens a SessionFactory in Init method of HttpModule and gets a new Session in BeginRequest and closes it in EndRequest. ...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.