Freigeben über


Übersetzen von Standardabfrageoperatoren

LINQ to SQL übersetzt Standardabfrageoperatoren in SQL-Befehle. Der Abfrageprozessor der Datenbank bestimmt die Ausführungssemantik der SQL-Übersetzung.

Standardabfrageoperatoren werden für Sequenzen definiert. Eine Sequenz wird sortiert und basiert auf der Referenzidentität für jedes Element der Sequenz. Weitere Informationen finden Sie unter Standard Query Operators Overview (C#) oder Standard Query Operators Overview (Visual Basic).

SQL behandelt in erster Linie ungeordnete Wertesätze. Die Sortierung ist in der Regel ein explizit angegebener Nachbearbeitungsvorgang, der auf das Endergebnis einer Abfrage und nicht auf Zwischenergebnisse angewendet wird. Die Identität wird durch Werte definiert. Aus diesem Grund befassen sich SQL-Abfragen mit Multisets (so genannten bags) und nicht mit Sätzen.

In den folgenden Absätzen werden die Unterschiede zwischen den Standardabfrageoperatoren und deren SQL-Übersetzung für den SQL Server-Anbieter für LINQ to SQL beschrieben.

Operatorunterstützung

Verkettung

Die Concat Methode wird für sortierte Multisets definiert, bei denen die Reihenfolge des Empfängers und die Reihenfolge des Arguments identisch sind. Concat funktioniert wie UNION ALL bei den Multisets, gefolgt von der gemeinsamen Reihenfolge.

Der letzte Schritt ist die Sortierung in SQL, bevor Ergebnisse erstellt werden. Concat behält die Reihenfolge ihrer Argumente nicht bei. Um eine geeignete Reihenfolge sicherzustellen, müssen Sie die Ergebnisse von Concat explizit sortieren.

Überschneiden, außer Union

Die Intersect-Methode und die Except-Methode sind nur für Sätze gut definiert. Die Semantik für Multisets ist nicht definiert.

Die Union Methode wird für Multisets als ungeordnete Verkettung der Multisets definiert (effektiv das Ergebnis der UNION ALL-Klausel in SQL).

Take, Skip

Die Methoden Take und Skip sind nur für sortierte Sätze gut definiert. Die Semantik für ungeordnete Sätze oder Multisets ist nicht definiert.

Hinweis

Take und Skip bestimmte Einschränkungen aufweisen, wenn sie in Abfragen mit SQL Server 2000 verwendet werden. Weitere Informationen finden Sie im Eintrag "Überspringen und Übernehmen von Ausnahmen in SQL Server 2000" in der Problembehandlung.

Aufgrund von Einschränkungen bei der Sortierung in SQL versucht LINQ to SQL, die Sortierung des Arguments dieser Methoden auf das Ergebnis der Methode zu verschieben. Betrachten Sie beispielsweise die folgende LINQ to SQL-Abfrage:

var custQuery =
    (from cust in db.Customers
    where cust.City == "London"
    orderby cust.CustomerID
    select cust).Skip(1).Take(1);
Dim custQuery = _
    From cust In db.Customers _
    Where cust.City = "London" _
    Order By cust.CustomerID _
    Select cust Skip 1 Take 1

Die generierte SQL für diesen Code verschiebt die Sortierung wie folgt an das Ende:

SELECT TOP 1 [t0].[CustomerID], [t0].[CompanyName],
FROM [Customers] AS [t0]
WHERE (NOT (EXISTS(
    SELECT NULL AS [EMPTY]
    FROM (
        SELECT TOP 1 [t1].[CustomerID]
        FROM [Customers] AS [t1]
        WHERE [t1].[City] = @p0
        ORDER BY [t1].[CustomerID]
        ) AS [t2]
    WHERE [t0].[CustomerID] = [t2].[CustomerID]
    ))) AND ([t0].[City] = @p1)
ORDER BY [t0].[CustomerID]

Es wird offensichtlich, dass alle angegebenen Sortierungen konsistent sein müssen, wenn Take und Skip miteinander verkettet werden. Andernfalls sind die Ergebnisse nicht definiert.

Sowohl Take als auch Skip sind für nicht-negative, konstante, integrale Argumente auf der Grundlage der Spezifikation des Standardabfrage-Operators gut definiert.

Operatoren ohne Übersetzung

Die folgenden Methoden werden von LINQ to SQL nicht übersetzt. Der häufigste Grund ist der Unterschied zwischen ungeordneten Multisets und Sequenzen.

Betriebspersonal Grund
TakeWhile, SkipWhile SQL-Abfragen werden auf Multisets und nicht auf Sequenzen ausgeführt. ORDER BY muss die letzte Klausel sein, die auf die Ergebnisse angewendet wird. Aus diesem Grund gibt es keine allgemeine Übersetzung für diese beiden Methoden.
Reverse Die Übersetzung dieser Methode ist für einen sortierten Satz möglich, wird aber derzeit nicht von LINQ in SQL übersetzt.
Last, LastOrDefault Die Übersetzung dieser Methoden ist für einen sortierten Satz möglich, wird aber derzeit nicht von LINQ in SQL übersetzt.
ElementAt, ElementAtOrDefault SQL-Abfragen werden für Multisets ausgeführt, nicht für indizierbare Sequenzen.
DefaultIfEmpty (Überladung mit Standard-arg) Im Allgemeinen kann ein Standardwert nicht für ein beliebiges Tupel angegeben werden. NULL-Werte für Tupel sind in einigen Fällen durch äußere Joins möglich.

Ausdrucksübersetzung

Null-Semantik

LINQ to SQL erzwingt keine Nullvergleichsemantik für SQL. Vergleichsoperatoren werden syntaktisch in ihre SQL-Entsprechungen übersetzt. Aus diesem Grund spiegelt die Semantik die von Server- oder Verbindungseinstellungen definierte SQL-Semantik wider. Beispielsweise werden zwei NULL-Werte unter den Standardmäßigen SQL Server-Einstellungen als ungleich angesehen, aber Sie können die Einstellungen ändern, um die Semantik zu ändern. LINQ to SQL berücksichtigt beim Übersetzen von Abfragen keine Servereinstellungen.

Ein Vergleich mit dem Literal null wird in die entsprechende SQL-Version (is null oder is not null) übersetzt.

Der Wert von null in der Zusammenstellung wird von SQL-Server definiert. LINQ to SQL ändert die Sortierung nicht.

Aggregate

Die Aggregatmethode Sum des Standardabfrageoperators wertet für eine leere Sequenz oder für eine Sequenz, die nur Nullen enthält, auf Null aus. In LINQ to SQL bleiben die Semantik von SQL unverändert, und Sum wird als null ausgewertet anstelle von null, wenn es sich um eine leere Sequenz oder eine Sequenz handelt, die nur Nullen enthält.

SQL-Einschränkungen für Zwischenergebnisse gelten für Aggregate in LINQ to SQL. Die Sum 32-Bit-Ganzzahlmengen werden nicht mit 64-Bit-Ergebnissen berechnet. Ein Überlauf kann bei einer LINQ to SQL-Übersetzung von Sum auftreten, selbst wenn die Implementierung des Standardabfrageoperators keinen Überlauf für die entsprechende in-memory-Sequenz verursacht.

Ebenso wird die LINQ to SQL-Übersetzung von Average von Ganzzahlenwerten als integer berechnet, nicht als double.

Entitätsargumente

LINQ to SQL ermöglicht die Verwendung von Entitätstypen in den GroupBy und OrderBy methoden. Bei der Übersetzung dieser Operatoren wird die Verwendung eines Arguments eines bestimmten Typs als gleichwertig dazu betrachtet, alle Mitglieder dieses Typs anzugeben. Der folgende Code ist z. B. gleichwertig:

db.Customers.GroupBy(c => c);
db.Customers.GroupBy(c => new { c.CustomerID, c.ContactName });
db.Customers.GroupBy(Function(c) c)
db.Customers.GroupBy(Function(c) New With {c.CustomerID, _
    c.ContactName})

Gleichstellbare/ vergleichbare Argumente

Die Gleichheit von Argumenten ist bei der Implementierung der folgenden Methoden erforderlich:

LINQ to SQL unterstützt Gleichheit und Vergleich für flache Argumente, jedoch nicht für Argumente, die Sequenzen sind oder diese enthalten. Ein flaches Argument ist ein Typ, der einer SQL-Zeile zugeordnet werden kann. Eine Projektion von einem oder mehreren Entitätstypen, bei denen statisch festgestellt werden kann, dass sie keine Sequenz enthalten, wird als flaches Argument betrachtet.

Es folgen Beispiele für flache Argumente:

db.Customers.Select(c => c);
db.Customers.Select(c => new { c.CustomerID, c.City });
db.Orders.Select(o => new { o.OrderID, o.Customer.City });
db.Orders.Select(o => new { o.OrderID, o.Customer });	
db.Customers.Select(Function(c) c)
db.Customers.Select(Function(c) New With {c.CustomerID, c.City})
db.Orders.Select(Function(o) New With {o.OrderID, o.Customer.City})
db.Orders.Select(Function(o) New With {o.OrderID, o.Customer})

Im Folgenden sind Beispiele für nicht flache (hierarchische) Argumente aufgeführt:

// In the following line, c.Orders is a sequence.
db.Customers.Select(c => new { c.CustomerID, c.Orders });
// In the following line, the result has a sequence.
db.Customers.GroupBy(c => c.City);
' In the following line, c.Orders is a sequence.
db.Customers.Select(Function(c) New With {c.CustomerID, c.Orders})
' In the following line, the result has a sequence.
db.Customers.GroupBy(Function(c) c.City)

Übersetzung der Visual Basic-Funktion

Die folgenden Hilfsfunktionen, die vom Visual Basic-Compiler verwendet werden, werden in entsprechende SQL-Operatoren und -Funktionen übersetzt:

  • CompareString

  • DateTime.Compare

  • Decimal.Compare

  • IIf (in Microsoft.VisualBasic.Interaction)

Konvertierungsmethoden:

  • ToBoolean
  • ToSByte
  • ToByte
  • ToChar
  • ToCharArrayRankOne
  • ToDate
  • ToDecimal
  • ToDouble
  • ToInteger
  • ToUInteger
  • ToLong
  • ToULong
  • ToShort
  • ToUShort
  • ToSingle
  • ToString

Vererbungsunterstützung

Einschränkungen bei der Vererbungsabbildung

Weitere Informationen finden Sie unter Anleitung: Zuordnung von Vererbungshierarchien.

Vererbung in Abfragen

C#-Umwandlungen werden nur in Projektionen unterstützt. An anderer Stelle verwendete Umwandlungen werden nicht übersetzt, sonder ignoriert. Abgesehen von SQL-Funktionsnamen führt SQL tatsächlich nur das Äquivalent der Common Language Runtime (CLR) Convertdurch. Das heißt, SQL kann den Wert eines Typs in einen anderen ändern. Es gibt keine Entsprechung zu CLR-Umwandlungen, da es kein Konzept für die Neuinterpretation der gleichen Bits als die eines anderen Typs gibt. Aus diesem Grund funktioniert eine C#-Umwandlung nur lokal. Eine Remoteausführung ist nicht möglich.

Die Operatoren is und as, und die GetType Methode sind nicht auf den Select Operator beschränkt. Sie können auch in anderen Abfrageoperatoren verwendet werden.

SQL Server 2008-Unterstützung

Ab .NET Framework 3.5 SP1 unterstützt LINQ to SQL die Zuordnung zu neuen Datums- und Uhrzeittypen, die mit SQL Server 2008 eingeführt wurden. Es gibt jedoch einige Einschränkungen für die LINQ to SQL-Abfrageoperatoren, die Sie beim Betrieb mit Werten verwenden können, die diesen neuen Typen zugeordnet sind.

Nicht unterstützte Abfrageoperatoren

Die folgenden Abfrageoperatoren werden für Werte, die den neuen SQL Server-Datums- und Uhrzeittypen zugeordnet sind, nicht unterstützt: DATETIME2, , , DATETIMEund DATETIMEOFFSET.

  • Aggregate

  • Average

  • LastOrDefault

  • OfType

  • Sum

Weitere Informationen zum Zuordnen zu diesen SQL Server-Datums- und -Uhrzeittypen finden Sie unterSQL-CLR Typzuordnung.

SQL Server 2005-Unterstützung

LINQ to SQL unterstützt nicht die folgenden SQL Server 2005-Features:

  • Gespeicherte Prozeduren, die für SQL CLR geschrieben wurden.

  • Benutzerdefinierter Typ.

  • XML-Abfragefunktionen.

SQL Server 2000-Unterstützung

Die folgenden SQL Server 2000-Einschränkungen (im Vergleich zu Microsoft SQL Server 2005) wirken sich auf LINQ to SQL-Unterstützung aus.

Cross Apply-Operator und Outer Apply-Operator

Diese Operatoren sind in SQL Server 2000 nicht verfügbar. LINQ to SQL versucht, eine Reihe von Umformulierungen vorzunehmen, um sie durch passende Joins zu ersetzen.

Cross Apply und Outer Apply werden für Beziehungsnavigationen generiert. Der Satz von Abfragen, für die solche Umschreibungen möglich sind, ist nicht gut definiert. Aus diesem Grund ist der minimale Satz von Abfragen, die für SQL Server 2000 unterstützt werden, der Satz, der keine Beziehungsnavigation umfasst.

text / ntext

Die Datentypen text / ntext können in bestimmten Abfragevorgängen für varchar(max) / nvarchar(max), die von Microsoft SQL Server 2005 unterstützt werden, nicht verwendet werden.

Für diese Einschränkung steht keine Lösung zur Verfügung. Insbesondere können Sie kein Distinct() für ein Ergebnis verwenden, das Mitglieder enthält, die den text- oder ntext-Spalten zugeordnet sind.

Verhalten ausgelöst durch geschachtelte Abfragen

Die Bindung von SQL Server 2000 (bis einschließlich SP4) weist einige Eigenheiten auf, die durch geschachtelte Abfragen ausgelöst werden. Der Satz von SQL-Abfragen, die diese Idiosyncrasies auslösen, ist nicht gut definiert. Aus diesem Grund können Sie den Satz von LINQ to SQL-Abfragen nicht definieren, die SQL Server-Ausnahmen verursachen können.

Skip-Operator und Take-Operator

Take und Skip bestimmte Einschränkungen aufweisen, wenn sie in Abfragen mit SQL Server 2000 verwendet werden. Weitere Informationen finden Sie im Eintrag "Überspringen und Übernehmen von Ausnahmen in SQL Server 2000" in der Problembehandlung.

Objektmaterialisierung

Die Materialisierung erstellt CLR-Objekte aus Zeilen, die von einer oder mehreren SQL-Abfragen zurückgegeben werden.

  • Die folgenden Aufrufe werden lokal als Teil der Materialisierung ausgeführt :

    • Erbauer

    • ToString Methoden für Projektionen

    • Typumwandlungen in Projektionen

  • Methoden, die der AsEnumerable Methode folgen, werden lokal ausgeführt. Diese Methode verursacht keine sofortige Ausführung.

  • Sie können einen struct als Rückgabetyp eines Abfrageergebnisses oder als Element des Ergebnistyps verwenden. Entitäten müssen Klassen sein. Anonyme Typen werden als Klasseninstanzen materialisiert, aber benannte Strukturen (Nichtentitäten) können in der Projektion verwendet werden.

  • Ein Element des Rückgabetyps eines Abfrageergebnisses kann vom Typ IQueryable<T>sein. Er wird als lokale Auflistung materialisiert.

  • Die folgenden Methoden verursachen die sofortige Materialisierung der Sequenz, auf die die Methoden angewendet werden:

Siehe auch