2008-09-18 9 views
5

als # versierte Programmierer nicht-C Sprechen, ich bin in Bezug auf die Auswertung Semantik von LINQ-Abfragen wie die folgenden neugierig:Unterstützt LINQ-to-SQL kompilierbare Abfragen?

var people = from p in Person 
      where p.age < 18 
      select p 

var otherPeople = from p in people 
        where p.firstName equals "Daniel" 
        select p 

Unter der Annahme, dass Person eine ADO Einheit, die die age und firstName Felder definiert, was würde dies von einem Datenbankstandpunkt aus tun? Konnte die Abfrage people ausgeführt werden, um eine speicherinterne Struktur zu erstellen, die dann von der Abfrage otherPeople abgefragt würde? Oder würde die Konstruktion von otherPeople lediglich die Daten bezüglich der Abfrage von people ziehen und dann eine neue Datenbank-abgefragte Abfrage erzeugen? Also, wenn ich über diese beiden Abfragen iterierte, wie viele SQL-Anweisungen würden ausgeführt werden?

Antwort

12

Sie sind zusammensetzbar. Dies ist möglich, weil LINQ-Abfragen tatsächlich Ausdrücke sind (Code als Daten), die LINQ-Provider wie LINQ-to-SQL auswerten und entsprechendes SQL generieren können.

Da LINQ-Abfragen nur langsam ausgewertet werden (z. B. werden sie erst ausgeführt, wenn Sie über die Elemente iterieren), wird der angezeigte Code die Datenbank nicht wirklich berühren. Erst wenn Sie über andere Personen oder Personen iterieren, wird SQL generiert und ausgeführt.

1

people und otherPeople enthalten Objekte vom Typ IQueryable<Person>.

Wenn Sie beide separat durchlaufen, werden zwei Abfragen ausgeführt. Wenn Sie nur über otherPeople iterieren, wird die erwartete Abfrage mit zwei where-Klauseln ausgeführt.

Wenn Sie das tun .ToList() auf people und verwenden Sie die zurück List<Person> in der zweiten Abfrage statt Menschen, wird es LINQ-to-Objects und kein SQL ausgeführt wird.

Dieses Verhalten wird als verzögerte Ausführung bezeichnet. Das bedeutet, dass keine Abfrage durchgeführt wird, bis sie benötigt wird. Vor der Ausführung sind sie nur Ausdrucksbäume, die manipuliert werden, um die endgültige Abfrage zu formulieren.

0

Diese beiden Abfragen werden ausgeführt, wenn Sie versuchen, auf die endgültigen Ergebnisse zuzugreifen. Sie können versuchen, Original-SQL anzuzeigen, das aus DataContext-Objekteigenschaften generiert wurde.

3

Ja, die resultierende Abfrage ist zusammengesetzt. Es enthält die vollständige Where-Klausel. Aktivieren Sie SQL Profiling und versuchen Sie es selbst zu sehen.

Linq macht dies durch Ausdruck Bäume. Die erste linq-Anweisung erzeugt einen Ausdrucksbaum; Es führt die Abfrage nicht aus. Die zweite linq-Anweisung baut auf der Ausdrucksstruktur auf, die von der ersten erstellt wurde. Die Anweisung wird nur ausgeführt, wenn Sie die resultierende Auflistung aufzählen.

3
var people = from p in Person 
      where p.age < 18 
      select p 

übersetzt:

SELECT [t0].[PersonId], [t0].[Age], [t0].[FirstName] 
FROM [dbo].[Person] AS [t0] 
WHERE [t0].[Age] < @p0 

wo @ p0 wird als 18

var otherPeople = from p in people 
        where p.firstName equals "Daniel" 
        select p 

Verschiebt gesendet durch:

SELECT [t0].[PersonId], [t0].[Age], [t0].[FirstName] 
FROM [dbo].[Person] AS [t0] 
WHERE [t0].[FirstName] = @p0 

wo @ p0 wird durch als "geschickt Daniel "

var morePeople = from p1 in people 
       from p2 in otherPeople 
       where p1.PersonId == p2.PersonId 
       select p1; 

Verschiebt zu:

SELECT [t0].[PersonId], [t0].[Age], [t0].[FirstName] 
FROM [dbo].[Person] AS [t0], [dbo].[Person] AS [t1] 
WHERE ([t0].[PersonId] = [t1].[PersonId]) AND ([t0].[Age] < @p0) AND ([t1].[FirstName] = @p1) 

wo @ p0 18, @ p1 "Daniel"

Im Zweifelsfall rufen Sie die ToString() auf Ihrem IQueryable oder eine Textwriter auf die geben DataContext Log-Eigenschaft.