2012-06-18 8 views
7

Ich habe die folgende LINQ-Abfrage:Warum setzt LINQ-to-Entities diese Abfrage in eine Unterauswahl?

var queryGroups = (from p in db.cl_contact_event 
        select new Groups { inputFileName = p.input_file_name }).Distinct(); 

, die folgenden übersetzt wenn ausführen:

SELECT 
[Distinct1].[C1] AS [C1], 
[Distinct1].[input_file_name] AS [input_file_name] 
FROM (SELECT DISTINCT 
     [Extent1].[input_file_name] AS [input_file_name], 
     1 AS [C1] 
     FROM [mel].[cl_contact_event] AS [Extent1] 
) AS [Distinct1] 

Jetzt bin ich ziemlich sicher, dass der Grund eine Unterauswahl ist, weil ich die Basis-LINQ-Abfrage umgeben von() und dann .Distinct() ausführen, aber ich weiß nicht genug über LINQ, um sicher zu sein. Wenn das tatsächlich der Fall ist, gibt es eine Möglichkeit, meine Abfrage neu zu strukturieren/zu codieren, so dass eine Unterauswahl nicht auftritt?

Ich weiß, dass es wahrscheinlich scheint, dass ich nur hier bin, aber ich bin nur neugierig.

+0

Ist das [tag: linq-to-sql], [tag: linq-to-entities] oder [tag: linq-to-nhibernate]? –

+0

@DannyVarod linq-to-entities Ich glaube, seit ich EF4 verwende, frage ich eine Sybase-Datenbank. – Kittoes0124

+0

Ändern Sie in diesem Fall das verwendete Tag und aktualisieren Sie den Titel der Frage entsprechend. –

Antwort

4

In diesem vermute ich, dass die eigentliche Ursache der Unterabfrage der anonyme Typ Konstruktor ist. Da Sie keine bekannte Entität auswählen, sondern ein beliebiges Objekt, das aus anderen Entitätswerten erstellt wird, muss der EF-Parser sicherstellen, dass er die exakte Menge von Feldern erzeugen kann - ob aus einer einzelnen Tabelle, verknüpften Tabellen, berechneten Feldern oder anderen Unterabfragen usw. Der Ausdruck Tree Parser ist sehr gut darin, wann immer möglich SQL-Anweisungen aus LINQ-Abfragen zu schreiben, aber nicht allwissend. Es verarbeitet die Abfragen in einer systematischen Weise, die immer korrekte Ergebnisse liefert (in dem Sinne, dass Sie bekommen, wonach Sie gefragt haben), obwohl nicht immer optimale Ergebnisse.

Soweit die Abfrage neu schreiben, um die Unterauswahl zu beseitigen, zuerst aus: Ich sehe keine offensichtliche Möglichkeit, dies zu tun, die den anonymen Typ beseitigt und korrekte Ergebnisse erzeugt. Noch wichtiger ist jedoch, dass ich nicht stören würde. Moderne SQL-Server wie Sybase sind sehr intelligent - oft schlauer als der Entwickler - und sehr gut darin, aus einer Abfrage einen optimalen Abfrageplan zu erstellen. Abgesehen davon liebt EF Unterabfragen, da sie sehr gute Möglichkeiten bieten, komplexe Abfragen automatisiert zu schreiben. Sie finden sie oft auch dann, wenn Ihre LINQ-Abfrage sie nicht verwendet. Der Versuch, sie alle aus Ihren Anfragen zu eliminieren, wird schnell zur sinnlosen Übung.

+0

Danke für die ausgezeichnete und gut detaillierte Antwort. Ich wollte nur sicher sein, dass ich keine offensichtlichen Fehler mache. – Kittoes0124

4

Ich würde mir über diese besondere Situation überhaupt keine Sorgen machen. SQL Server (und höchstwahrscheinlich jede Unternehmensdatenbank) wird die äußere Select-Anweisung trotzdem optimieren. Ich würde theoretisieren, dass der Grund, warum diese SQL-Anweisung generiert wird, weil dies die allgemeinste und wiederverwendbare Anweisung ist. Aus meiner Erfahrung geschieht dies immer auf Distinct().