Dela via


Översättning av standardfrågeoperator

LINQ till SQL översätter Standard Query Operators till SQL-kommandon. Databasens frågeprocessor avgör körningssemantiken för SQL-översättning.

Vanliga frågeoperatorer definieras mot sekvenser. En sekvens ordnas och förlitar sig på referensidentitet för varje element i sekvensen. Mer information finns i Översikt över vanliga frågeoperatorer (C#) eller Översikt över standardfrågasoperatorer (Visual Basic).

SQL hanterar främst osorterade uppsättningar med värden. Beställning är vanligtvis en uttryckligen angiven efterbearbetningsåtgärd som tillämpas på slutresultatet av en fråga i stället för mellanliggande resultat. Identitet definieras av värden. Därför tolkas SQL-frågor för att hantera flera uppsättningar (påsar) i stället för uppsättningar.

Följande stycken beskriver skillnaderna mellan Standard Query Operators och deras SQL-översättning för SQL Server-providern för LINQ till SQL.

Stöd för operatör

Concat

Metoden Concat definieras för ordnade flera uppsättningar där ordningen på mottagaren och argumentets ordning är desamma. Concat fungerar som UNION ALL över flera enheter följt av den gemensamma ordningen.

Det sista steget är att beställa i SQL innan resultaten skapas. Concat bevarar inte ordningen på argumenten. För att säkerställa lämplig ordning måste du uttryckligen beställa resultatet av Concat.

Intersect, Except, Union

Metoderna Intersect och Except är väldefinierade endast för uppsättningar. Semantiken för flera enheter är odefinierad.

Metoden Union definieras för flera uppsättningar som den osorterade sammanlänkningen av flera uppsättningar (i praktiken resultatet av UNION ALL-satsen i SQL).

Ta, hoppa över

Take och Skip metoder är väldefinierade endast mot ordnade uppsättningar. Semantiken för osorterade uppsättningar eller flera uppsättningar är odefinierad.

Kommentar

Take och Skip har vissa begränsningar när de används i frågor mot SQL Server 2000. Mer information finns i posten Hoppa över och ta undantag i SQL Server 2000 i Felsökning.

På grund av begränsningar i ordningen i SQL försöker LINQ till SQL flytta ordningen på argumentet för dessa metoder till resultatet av metoden. Tänk till exempel på följande LINQ till SQL-fråga:

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

Den genererade SQL-filen för den här koden flyttar beställningen till slutet enligt följande:

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]

Det blir uppenbart att all angiven ordning måste vara konsekvent när Take och Skip är sammanlänkade. Annars är resultatet odefinierat.

Både Take och Skip är väldefinierade för icke-negativa, konstanta integralargument baserat på Standard Query Operator-specifikationen.

Operatorer utan översättning

Följande metoder översätts inte av LINQ till SQL. Den vanligaste orsaken är skillnaden mellan osorterade flermängder och sekvenser.

Operatorer Motivering
TakeWhile, SkipWhile SQL-frågor fungerar på flera uppsättningar, inte på sekvenser. ORDER BY måste vara den sista satsen som tillämpas på resultaten. Därför finns det ingen generell översättning för dessa två metoder.
Reverse Översättning av den här metoden är möjlig för en ordnad uppsättning men översätts för närvarande inte av LINQ till SQL.
Last, LastOrDefault Översättning av dessa metoder är möjlig för en ordnad uppsättning men översätts för närvarande inte av LINQ till SQL.
ElementAt, ElementAtOrDefault SQL-frågor fungerar på flera uppsättningar, inte på indexerbara sekvenser.
DefaultIfEmpty (överlagring med standard arg) I allmänhet går det inte att ange ett standardvärde för en godtycklig tuppeln. Null-värden för tupplar är i vissa fall möjliga via yttre kopplingar.

Översättning av uttryck

Null-semantik

LINQ till SQL tillämpar inte null-jämförelsesemantik på SQL. Jämförelseoperatorer översätts syntaktiskt till sina SQL-motsvarigheter. Därför återspeglar semantiken SQL-semantik som definieras av server- eller anslutningsinställningar. Till exempel anses två null-värden vara ojämlika under standardinställningarna för SQL Server, men du kan ändra inställningarna för att ändra semantiken. LINQ till SQL tar inte hänsyn till serverinställningar när frågor översätts.

En jämförelse med literal null översätts till lämplig SQL-version (is null eller is not null).

Värdet null för i sortering definieras av SQL Server. LINQ till SQL ändrar inte sorteringen.

Aggregeringar

Aggregeringsmetoden Sum Standard Query Operator utvärderas till noll för en tom sekvens eller för en sekvens som endast innehåller nullvärden. I LINQ till SQL lämnas semantiken för SQL oförändrad och Sum utvärderas till null i stället för noll för en tom sekvens eller för en sekvens som endast innehåller nullvärden.

SQL-begränsningar för mellanliggande resultat gäller för aggregeringar i LINQ till SQL. Mängden Sum 32-bitars heltal beräknas inte med hjälp av 64-bitarsresultat. Spill kan uppstå för en LINQ till SQL-översättning av , även om implementeringen av SumStandard Query Operator inte orsakar ett spill för motsvarande minnesinterna sekvens.

På samma sätt beräknas LINQ till SQL-översättningen av Average heltalsvärden som en integer, inte som .double

Entitetsargument

LINQ till SQL gör att entitetstyper kan användas i GroupBy metoderna och OrderBy . I översättningen av dessa operatorer anses användningen av ett argument av en typ vara detsamma som att ange alla medlemmar av den typen. Följande kod är till exempel likvärdig:

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})

Ekvabel/Jämförbara argument

Argumentens likhet krävs i implementeringen av följande metoder:

LINQ till SQL stöder likhet och jämförelse för platta argument, men inte för argument som är eller innehåller sekvenser. Ett platt argument är en typ som kan mappas till en SQL-rad. En projektion av en eller flera entitetstyper som statiskt kan fastställas att inte innehålla en sekvens betraktas som ett platt argument.

Följande är exempel på flata argument:

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})

Följande är exempel på icke-platta (hierarkiska) argument:

// 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)

Visual Basic-funktionsöversättning

Följande hjälpfunktioner som används av Visual Basic-kompilatorn översätts till motsvarande SQL-operatorer och -funktioner:

  • CompareString

  • DateTime.Compare

  • Decimal.Compare

  • IIf (in Microsoft.VisualBasic.Interaction)

Konverteringsmetoder:

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

Arvsstöd

Begränsningar för arvsmappning

Mer information finns i Så här: Mappa arvshierarkier.

Arv i frågor

C#-avgjutningar stöds endast i projektion. Avgjutningar som används någon annanstans översätts inte och ignoreras. Förutom SQL-funktionsnamn utför SQL egentligen bara motsvarigheten till CLR (Common Language Runtime). Convert Sql kan alltså ändra värdet för en typ till en annan. Det finns ingen motsvarighet till CLR-gjutning eftersom det inte finns något begrepp om att omtolka samma bitar som de av en annan typ. Det är därför en C#-rollbesättning endast fungerar lokalt. Den är inte fjärransluten.

Operatorerna och is as, och GetType -metoden är inte begränsade till operatorn Select . De kan också användas i andra frågeoperatorer.

Stöd för SQL Server 2008

Från och med .NET Framework 3.5 SP1 stöder LINQ till SQL mappning till nya datum- och tidstyper som introducerats med SQL Server 2008. Det finns dock vissa begränsningar för LINQ till SQL-frågeoperatorer som du kan använda när du arbetar mot värden som mappas till dessa nya typer.

Frågeoperatorer som inte stöds

Följande frågeoperatorer stöds inte för värden som mappas till de nya datum- och tidstyperna för SQL Server: DATETIME2, DATE, TIMEoch DATETIMEOFFSET.

  • Aggregate

  • Average

  • LastOrDefault

  • OfType

  • Sum

Mer information om mappning till dessa datum- och tidstyper för SQL Server finns i SQL-CLR-typmappning.

Stöd för SQL Server 2005

LINQ till SQL stöder inte följande SQL Server 2005-funktioner:

  • Lagrade procedurer skrivna för SQL CLR.

  • Användardefinierad typ.

  • XML-frågefunktioner.

Stöd för SQL Server 2000

Följande SQL Server 2000-begränsningar (jämfört med Microsoft SQL Server 2005) påverkar LINQ till SQL-stöd.

Cross Apply- och Outer Apply-operatorer

Dessa operatorer är inte tillgängliga i SQL Server 2000. LINQ till SQL provar en serie omskrivningar för att ersätta dem med lämpliga kopplingar.

Cross Apply och Outer Apply genereras för relationsnavigeringar. Den uppsättning frågor som sådana omskrivningar är möjliga för är inte väldefinierade. Därför är den minimala uppsättningen frågor som stöds för SQL Server 2000 den uppsättning som inte omfattar relationsnavigering.

text/ntext

Datatyper text / ntext kan inte användas i vissa frågeåtgärder mot varchar(max) / nvarchar(max), som stöds av Microsoft SQL Server 2005.

Ingen lösning är tillgänglig för den här begränsningen. Mer specifikt kan du inte använda Distinct() på resultat som innehåller medlemmar som är mappade till text eller ntext kolumner.

Beteende som utlöses av kapslade frågor

SQL Server 2000 (via SP4) har vissa idiosynkraser som utlöses av kapslade frågor. Den uppsättning SQL-frågor som utlöser dessa idiosynkraser är inte väldefinierad. Därför kan du inte definiera uppsättningen LINQ till SQL-frågor som kan orsaka SQL Server-undantag.

Hoppa över och ta operatorer

Take och Skip har vissa begränsningar när de används i frågor mot SQL Server 2000. Mer information finns i posten Hoppa över och ta undantag i SQL Server 2000 i Felsökning.

Objektmaterialisering

Materialisering skapar CLR-objekt från rader som returneras av en eller flera SQL-frågor.

  • Följande anrop körs lokalt som en del av materialiseringen:

    • Konstruktorer

    • ToString metoder i projektioner

    • Typgjutningar i projektioner

  • Metoder som följer AsEnumerable metoden körs lokalt. Den här metoden orsakar inte omedelbar körning.

  • Du kan använda en struct som returtyp för ett frågeresultat eller som medlem av resultattypen. Entiteter måste vara klasser. Anonyma typer materialiseras som klassinstanser, men namngivna structs (icke-entiteter) kan användas i projektion.

  • En medlem av returtypen för ett frågeresultat kan vara av typen IQueryable<T>. Den materialiseras som en lokal samling.

  • Följande metoder orsakar omedelbar materialisering av sekvensen som metoderna tillämpas på:

Se även