Standard Query Operator Translation
LINQ naar SQL vertaalt Standard-queryoperators naar SQL-opdrachten. De queryprocessor van de database bepaalt de uitvoeringssemantiek van SQL-vertaling.
Standaardqueryoperators worden gedefinieerd op basis van reeksen. Een reeks wordt geordend en is afhankelijk van referentie-identiteit voor elk element van de reeks. Zie Overzicht van Standard-queryoperators (C#) of Overzicht van Standard-queryoperators (Visual Basic) voor meer informatie.
SQL behandelt voornamelijk niet-geordende sets waarden. Ordenen is doorgaans een expliciete, naverwerkingsbewerking die wordt toegepast op het uiteindelijke resultaat van een query in plaats van op tussenliggende resultaten. Identiteit wordt gedefinieerd door waarden. Daarom worden SQL-query's begrepen om te gaan met multisets (tassen) in plaats van sets.
In de volgende alinea's worden de verschillen beschreven tussen de Standard-queryoperators en de SQL-vertaling voor de SQL Server-provider voor LINQ naar SQL.
Operatorondersteuning
Concat
De Concat methode wordt gedefinieerd voor geordende multisets waarbij de volgorde van de ontvanger en de volgorde van het argument hetzelfde zijn. Concat werkt als UNION ALL
boven de multisets gevolgd door de gemeenschappelijke volgorde.
De laatste stap is het ordenen in SQL voordat de resultaten worden geproduceerd. Concat behoudt de volgorde van de argumenten niet. Om de juiste volgorde te garanderen, moet u de resultaten Concatvan .
Intersect, Except, Union
De Intersect en Except methoden zijn alleen goed gedefinieerd voor sets. De semantiek voor meerderesets is niet gedefinieerd.
De Union methode wordt gedefinieerd voor meerderesets als de niet-geordende samenvoeging van de multisets (effectief het resultaat van de UNION ALL-component in SQL).
Take, Skip
Take en Skip methoden zijn alleen goed gedefinieerd op basis van geordende sets. De semantiek voor niet-geordende sets of multisets is niet gedefinieerd.
Notitie
Take en Skip bepaalde beperkingen hebben wanneer ze worden gebruikt in query's voor SQL Server 2000. Zie de vermelding 'Skip and Take Exceptions in SQL Server 2000' (Uitzonderingen overslaan en maken in SQL Server 2000) in Probleemoplossing voor meer informatie.
Vanwege beperkingen voor het ordenen in SQL probeert LINQ naar SQL de volgorde van het argument van deze methoden te verplaatsen naar het resultaat van de methode. Denk bijvoorbeeld aan de volgende LINQ naar SQL-query:
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
De gegenereerde SQL voor deze code verplaatst de volgorde als volgt naar het einde:
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]
Het wordt duidelijk dat alle opgegeven volgorde consistent moet zijn wanneer Take en Skip aan elkaar zijn gekoppeld. Anders zijn de resultaten niet gedefinieerd.
Beide Take en Skip zijn goed gedefinieerd voor niet-negatieve, constante integrale argumenten op basis van de standaardqueryoperatorspecificatie.
Operators zonder vertaling
De volgende methoden worden niet vertaald door LINQ naar SQL. De meest voorkomende reden is het verschil tussen niet-geordende multisets en reeksen.
Operators | Reden |
---|---|
TakeWhile, SkipWhile | SQL-query's worden uitgevoerd op meerderesets, niet op reeksen. ORDER BY moet de laatste component zijn die op de resultaten wordt toegepast. Daarom is er geen vertaling voor algemeen gebruik voor deze twee methoden. |
Reverse | Vertaling van deze methode is mogelijk voor een geordende set, maar wordt momenteel niet vertaald door LINQ naar SQL. |
Last, LastOrDefault | Vertaling van deze methoden is mogelijk voor een geordende set, maar wordt momenteel niet vertaald door LINQ naar SQL. |
ElementAt, ElementAtOrDefault | SQL-query's worden uitgevoerd op meerderesets, niet op indexeerbare reeksen. |
DefaultIfEmpty (overbelasting met standaard arg) | Over het algemeen kan een standaardwaarde niet worden opgegeven voor een willekeurige tuple. Null-waarden voor tuples zijn in sommige gevallen mogelijk via outer joins. |
Expressieomzetting
Null-semantiek
LINQ naar SQL legt geen null-vergelijkingssemantiek op voor SQL. Vergelijkingsoperatoren worden syntactisch vertaald naar hun SQL-equivalenten. Daarom weerspiegelen de semantiek SQL-semantiek die zijn gedefinieerd door server- of verbindingsinstellingen. Twee null-waarden worden bijvoorbeeld als ongelijk beschouwd onder de standaardINSTELLINGEN van SQL Server, maar u kunt de instellingen wijzigen om de semantiek te wijzigen. LINQ naar SQL houdt geen rekening met serverinstellingen wanneer query's worden vertaald.
Een vergelijking met de letterlijke null wordt vertaald naar de juiste SQL-versie (is null
of is not null
).
De waarde van null
in sortering wordt gedefinieerd door SQL Server. LINQ naar SQL wijzigt de sortering niet.
Aggregaties
De statistische methode Sum Standard Query Operator evalueert naar nul voor een lege reeks of voor een reeks die alleen null-waarden bevat. In LINQ naar SQL blijven de semantiek van SQL ongewijzigd en Sum worden ze geëvalueerd in null
plaats van nul voor een lege reeks of voor een reeks die alleen null-waarden bevat.
SQL-beperkingen voor tussenliggende resultaten zijn van toepassing op aggregaties in LINQ naar SQL. De Sum 32-bits gehele getallen worden niet berekend met behulp van 64-bits resultaten. Overloop kan optreden voor een LINQ naar SQL-vertaling van Sum, zelfs als de implementatie van de Standard-queryoperator geen overloop veroorzaakt voor de bijbehorende in-memory reeks.
Op dezelfde manier wordt de LINQ naar SQL-vertaling van Average gehele getallen berekend als een integer
, niet als een double
.
Entiteitargumenten
LINQ naar SQL maakt het mogelijk om entiteitstypen te gebruiken in de GroupBy en OrderBy methoden. In de vertaling van deze operators wordt het gebruik van een argument van een type beschouwd als het equivalent van het opgeven van alle leden van dat type. De volgende code is bijvoorbeeld gelijk:
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})
Gelijkbare/vergelijkbare argumenten
Gelijkheid van argumenten is vereist bij de implementatie van de volgende methoden:
LINQ naar SQL ondersteunt gelijkheid en vergelijking voor platte argumenten, maar niet voor argumenten die reeksen zijn of bevatten. Een plat argument is een type dat kan worden toegewezen aan een SQL-rij. Een projectie van een of meer entiteitstypen die statisch kunnen worden bepaald om geen reeks te bevatten, wordt beschouwd als een plat argument.
Hier volgen enkele voorbeelden van platte argumenten:
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})
Hier volgen enkele voorbeelden van niet-platte (hiërarchische) argumenten:
// 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 Function Translation
De volgende helperfuncties die door de Visual Basic-compiler worden gebruikt, worden vertaald naar bijbehorende SQL-operators en -functies:
CompareString
DateTime.Compare
Decimal.Compare
IIf (in Microsoft.VisualBasic.Interaction)
Conversiemethoden:
ToBoolean
ToSByte
ToByte
ToChar
ToCharArrayRankOne
ToDate
ToDecimal
ToDouble
ToInteger
ToUInteger
ToLong
ToULong
ToShort
ToUShort
ToSingle
ToString
Overnameondersteuning
Beperkingen voor overnametoewijzing
Zie Procedure: Overnamehiërarchieën toewijzen voor meer informatie.
Overname in query's
C#-casts worden alleen ondersteund in projectie. Casts die elders worden gebruikt, worden niet vertaald en genegeerd. Afgezien van sql-functienamen, voert SQL alleen het equivalent van de Common Language Runtime (CLR) Convertuit. Dat wil gezegd, SQL kan de waarde van het ene type wijzigen in een ander type. Er is geen equivalent van CLR cast omdat er geen concept is van het opnieuw interpreteren van dezelfde bits als die van een ander type. Daarom werkt een C#-cast alleen lokaal. Het is niet op afstand.
De operators is
en , en as
de GetType
methode zijn niet beperkt tot de Select
operator. Ze kunnen ook worden gebruikt in andere queryoperators.
Ondersteuning voor SQL Server 2008
Vanaf .NET Framework 3.5 SP1 ondersteunt LINQ naar SQL toewijzing aan nieuwe datum- en tijdtypen die zijn geïntroduceerd met SQL Server 2008. Er zijn echter enkele beperkingen voor de LINQ voor SQL-queryoperators die u kunt gebruiken wanneer u werkt op basis van waarden die zijn toegewezen aan deze nieuwe typen.
Niet-ondersteunde queryoperators
De volgende queryoperators worden niet ondersteund op waarden die zijn toegewezen aan de nieuwe sql Server-datum- en tijdtypen: DATETIME2
, DATE
, TIME
en DATETIMEOFFSET
.
Aggregate
Average
LastOrDefault
OfType
Sum
Zie SQL-CLR-typetoewijzing voor meer informatie over toewijzing aan deze SQL Server-datum- en tijdtypen.
Ondersteuning voor SQL Server 2005
LINQ naar SQL biedt geen ondersteuning voor de volgende SQL Server 2005-functies:
Opgeslagen procedures die zijn geschreven voor SQL CLR.
Door de gebruiker gedefinieerd type.
XML-queryfuncties.
Ondersteuning voor SQL Server 2000
De volgende beperkingen van SQL Server 2000 (vergeleken met Microsoft SQL Server 2005) zijn van invloed op LINQ naar SQL-ondersteuning.
Operators voor kruislings toepassen en buitenste toepassen
Deze operators zijn niet beschikbaar in SQL Server 2000. LINQ naar SQL probeert een reeks herschrijven om ze te vervangen door de juiste joins.
Cross Apply
en Outer Apply
worden gegenereerd voor relatienavigatie. De set query's waarvoor dergelijke herschrijven mogelijk zijn, is niet goed gedefinieerd. Daarom is de minimale set query's die worden ondersteund voor SQL Server 2000, de set die geen relatienavigatie omvat.
tekst/ntekst
Gegevenstypen text
/ ntext
kunnen niet worden gebruikt in bepaalde querybewerkingen, varchar(max)
/ nvarchar(max)
die worden ondersteund door Microsoft SQL Server 2005.
Er is geen oplossing beschikbaar voor deze beperking. U kunt met name geen enkel resultaat gebruiken Distinct()
dat leden bevat die zijn toegewezen aan text
of ntext
kolommen.
Gedrag geactiveerd door geneste query's
Sql Server 2000 -binder (via SP4) bevat enkele idiosyncrasies die worden geactiveerd door geneste query's. De set SQL-query's waarmee deze idiosyncrasies worden geactiveerd, is niet goed gedefinieerd. Daarom kunt u de set LINQ niet definiëren voor SQL-query's die sql Server-uitzonderingen kunnen veroorzaken.
Operators overslaan en overnemen
Take en Skip bepaalde beperkingen hebben wanneer ze worden gebruikt in query's voor SQL Server 2000. Zie de vermelding 'Skip and Take Exceptions in SQL Server 2000' (Uitzonderingen overslaan en maken in SQL Server 2000) in Probleemoplossing voor meer informatie.
Object materialisatie
Materialisatie maakt CLR-objecten op basis van rijen die worden geretourneerd door een of meer SQL-query's.
De volgende aanroepen worden lokaal uitgevoerd als onderdeel van materialisatie:
Constructors
ToString
methoden in projectiesType casts in projecties
Methoden die de AsEnumerable methode volgen, worden lokaal uitgevoerd. Deze methode veroorzaakt geen onmiddellijke uitvoering.
U kunt een
struct
als retourtype van een queryresultaat of als lid van het resultaattype gebruiken. Entiteiten moeten klassen zijn. Anonieme typen worden gerealiseerd als klasse-exemplaren, maar benoemde structs (niet-entiteiten) kunnen worden gebruikt in projectie.Een lid van het retourtype van een queryresultaat kan van het type IQueryable<T>zijn. Het wordt gerealiseerd als een lokale verzameling.
De volgende methoden veroorzaken de onmiddellijke materialisatie van de volgorde waarop de methoden worden toegepast: