簡體   English   中英

這些LINQ查詢之間有什么區別

[英]What is the difference between these LINQ queries

我一直在使用一些LINQ over Entities,我得到了奇怪的結果,我想得到解釋......

給出以下LINQ查詢,

// Sample # 1
IEnumerable<GroupInformation> groupingInfo;
groupingInfo = from a in context.AccountingTransaction
               group a by a.Type into grp
               select new GroupInformation()
               {
                   GroupName = grp.Key,
                   GroupCount = grp.Count()
               };

我得到以下SQL查詢(取自SQL Profiler):

SELECT 
    1 AS [C1], 
    [GroupBy1].[K1] AS [Type], 
    [GroupBy1].[A1] AS [C2]
    FROM ( SELECT 
        [Extent1].[Type] AS [K1], 
        COUNT(1) AS [A1]
        FROM [dbo].[AccountingTransaction] AS [Extent1]
        GROUP BY [Extent1].[Type]
    )  AS [GroupBy1]

到現在為止還挺好。

如果我將我的LINQ查詢更改為:

// Sample # 2
groupingInfo = context.AccountingTransaction.
                 GroupBy(a => a.Type).
                 Select(grp => new GroupInformation()
                               {
                                   GroupName = grp.Key,
                                   GroupCount = grp.Count()
                               });

它產生完全相同的SQL查詢。 我感覺合理。

這是有趣的部分...如果我將我的LINQ查詢更改為:

// Sample # 3
IEnumerable<AccountingTransaction> accounts;
IEnumerable<IGrouping<object, AccountingTransaction>> groups;
IEnumerable<GroupInformation> groupingInfo;

accounts = context.AccountingTransaction;
groups = accounts.GroupBy(a => a.Type);
groupingInfo = groups.Select(grp => new GroupInformation()
                  {
                      GroupName = grp.Key,
                      GroupCount = grp.Count()
                  });

執行以下SQL(我從實際查詢中刪除了一些字段,但表中的所有字段(~15個字段)都包含在查詢中,兩次):

SELECT 
    [Project2].[C1] AS [C1], 
    [Project2].[Type] AS [Type], 
    [Project2].[C2] AS [C2], 
    [Project2].[Id] AS [Id], 
    [Project2].[TimeStamp] AS [TimeStamp], 
    -- <snip>
    FROM ( SELECT 
        [Distinct1].[Type] AS [Type], 
        1 AS [C1], 
        [Extent2].[Id] AS [Id], 
        [Extent2].[TimeStamp] AS [TimeStamp], 
        -- <snip>
        CASE WHEN ([Extent2].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2]
        FROM   (SELECT DISTINCT 
            [Extent1].[Type] AS [Type]
            FROM [dbo].[AccountingTransaction] AS [Extent1] ) AS [Distinct1]
        LEFT OUTER JOIN [dbo].[AccountingTransaction] AS [Extent2] ON [Distinct1].[Type] = [Extent2].[Type]
    )  AS [Project2]
    ORDER BY [Project2].[Type] ASC, [Project2].[C2] ASC

為什么生成的SQL如此不同? 畢竟,執行完全相同的代碼,只是示例#3使用中間變量來完成相同的工作!

另外,如果我這樣做:

Console.WriteLine(groupingInfo.ToString());

對於示例#1和示例#2,我得到了與SQL事件探查器捕獲的完全相同的查詢,但對於示例#3,我得到:

System.Linq.Enumerable+WhereSelectEnumerableIterator`2[System.Linq.IGrouping`2[System.Object,TestLinq.AccountingTransaction],TestLinq.GroupInformation]

有什么不同? 如果我在多個指令中拆分LINQ查詢,為什么我不能獲得LINQ生成的SQL查詢?

ulitmate的目標是能夠在運行時向查詢(Where,OrderBy等)添加運算符。

順便說一下,我在EF 4.0和EF 6.0中看到過這種行為。

謝謝您的幫助。

原因是因為在您的第三次嘗試中,您將accounts稱為IEnumerable<AccountingTransaction> ,這將導致使用Linq-To-ObjectsEnumerable.GroupByEnumerable.Select )調用查詢

另一方面,在第一次和第二次嘗試中,對AccountingTransaction的引用保留為IQueryable<AccountingTransaction>並且將使用Linq-To-Entities執行查詢,然后Linq-To-Entities將其轉換為適當的SQL語句。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM