6

Tôi đã lừa xung quanh với một số LINQ trên thực thể và tôi nhận được kết quả lạ và tôi muốn nhận được giải thích ...Sự khác nhau giữa các truy vấn LINQ

Cho truy vấn LINQ sau đây,

// 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() 
       }; 

tôi nhận được truy vấn sau đây SQL (lấy từ 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] 

Cho đến nay rất tốt.

Nếu tôi thay đổi truy vấn LINQ to:

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

nó mang lại cho các truy vấn SQL cùng chính xác. Có nghĩa với tôi.

Ở đây có phần thú vị ... Nếu tôi thay đổi truy vấn LINQ to:

// 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 sau đây được thực hiện (tôi lột một vài trong số các lĩnh vực từ truy vấn thực tế, nhưng tất cả các lĩnh vực từ bảng (~ 15 trường) được bao gồm trong truy vấn, hai lần):

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 

Tại sao các SQL được tạo khác nhau? Sau khi tất cả, chính xác cùng một mã được thực hiện, nó chỉ là mẫu # 3 đang sử dụng các biến trung gian để có được cùng một công việc làm!

Ngoài ra, nếu tôi làm:

Console.WriteLine(groupingInfo.ToString()); 

cho mẫu # 1 và mẫu # 2, tôi nhận được cùng một truy vấn chính xác được chụp bởi SQL Profiler, nhưng đối với mẫu # 3, tôi nhận được:

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

Sự khác biệt là gì? Tại sao tôi không thể nhận được truy vấn SQL được tạo ra bởi LINQ nếu tôi chia truy vấn LINQ trong nhiều hướng dẫn?

Mục tiêu của ulitmate là có thể thêm toán tử vào truy vấn (Where, OrderBy, v.v.) tại thời gian chạy.

BTW, tôi đã thấy hành vi này trong EF 4.0 và EF 6.0.

Cảm ơn sự giúp đỡ của bạn.

+3

Tôi thậm chí không thể hiểu được lý do ai đó có thể đã downvoted điều này. Giải thích? – Yuck

Trả lời

7

Lý do là vì trong nỗ lực thứ ba của bạn, bạn đang đề cập đến accounts như IEnumerable<AccountingTransaction> đó sẽ gây ra các truy vấn được gọi bằng LINQ-To-Objects (Enumerable.GroupByEnumerable.Select)

Mặt khác, trong lần thử đầu tiên và lần thứ hai, tham chiếu đến AccountingTransaction được giữ nguyên là IQueryable<AccountingTransaction> và truy vấn sẽ được thực thi bằng cách sử dụng LINQ-To-Entities sau đó sẽ biến nó thành câu lệnh SQL thích hợp.

+0

Vì vậy, sẽ 'nhóm = tài khoản.GroupBy (a => a.Type) .AsQueryable();' làm các trick? Hoặc, chỉ cần sử dụng 'var' cho khai báo biến? – Yuck

+1

'accounts.AsQueryable(). GroupBy (a => a.Type)' sẽ làm. – haim770

+0

hoặc chỉ 'var accounts = context.AccountingTransaction; '... – Magnus

Các vấn đề liên quan