Ich habe mit einigen LINQ über Entities herum täuscht und ich bin immer seltsame Ergebnisse, und ich möchte eine Erklärung bekommen ...Was ist der Unterschied zwischen diesen LINQ-Abfragen
die folgende LINQ-Abfrage gegeben,
// 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()
};
erhalte ich die folgende SQL-Abfrage (aus 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]
so weit so gut.
Wenn ich meine LINQ-Abfrage zu ändern:
// Sample # 2
groupingInfo = context.AccountingTransaction.
GroupBy(a => a.Type).
Select(grp => new GroupInformation()
{
GroupName = grp.Key,
GroupCount = grp.Count()
});
es ergibt sich auf die exakt gleiche SQL-Abfrage. Für mich ergibt das Sinn.
Hier kommt der interessante Teil ... Wenn ich meine LINQ-Abfrage zu ändern:
// 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()
});
die folgende SQL ausgeführt wird (ich einige der Felder aus der aktuellen Abfrage gestrippt, aber alle Felder aus die Tabelle (~ 15 Felder) wurden zweimal in die Abfrage aufgenommen:
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
Warum sind die erzeugten SQL-Dateien so unterschiedlich? Schließlich wird genau derselbe Code ausgeführt, nur dass Beispiel 3 Zwischenvariablen verwendet, um die gleiche Aufgabe zu erledigen!
Auch, wenn ich tun:
Console.WriteLine(groupingInfo.ToString());
für Probe # 1 und Probe # 2, bekomme ich genau die gleiche Abfrage, die drei von SQL Profiler, aber für die Probe # gefangen genommen wurde, erhalte ich:
System.Linq.Enumerable+WhereSelectEnumerableIterator`2[System.Linq.IGrouping`2[System.Object,TestLinq.AccountingTransaction],TestLinq.GroupInformation]
Was ist der Unterschied? Warum kann ich die von LINQ generierte SQL-Abfrage nicht erhalten, wenn ich die LINQ-Abfrage in mehrere Anweisungen aufspalte?
Das ultimative Ziel besteht darin, Operatoren zu der Abfrage (Where, OrderBy usw.) zur Laufzeit hinzuzufügen.
BTW, ich habe dieses Verhalten in EF 4.0 und EF 6.0 gesehen.
Vielen Dank für Ihre Hilfe.
Ich kann nicht einmal einen Grund ausloten, warum jemand das hätte abwerten können. Erklären? – Yuck