Ö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
, TIME
och 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 projektionerTypgjutningar 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å: