Převod standardních operátorů dotazů
LINQ to SQL překládá standardní operátory dotazů na příkazy SQL. Procesor dotazů databáze určuje sémantiku provádění překladu SQL.
Standardní operátory dotazů jsou definovány proti sekvencí. Sekvence je seřazená a spoléhá na referenční identitu pro každý prvek sekvence. Další informace najdete v tématu Přehled operátorů standardních dotazů (C#) nebo Přehled operátorů standardních dotazů (Visual Basic).
SQL se zabývá primárně neuspořádanými sadami hodnot. Řazení je obvykle explicitně uvedená operace následného zpracování, která se použije na konečný výsledek dotazu, nikoli na přechodné výsledky. Identita je definována hodnotami. Z tohoto důvodu jsou dotazy SQL srozumitelné pro práci s více sadami (taškami) místo sad.
Následující odstavce popisují rozdíly mezi standardními operátory dotazů a jejich překladem SQL pro zprostředkovatele SQL Serveru pro LINQ to SQL.
Podpora operátorů
Concat
Metoda Concat je definována pro uspořádané více sad, kde pořadí příjemce a pořadí argumentu jsou stejné. Concat funguje stejně jako UNION ALL
u více sad následovaných společným pořadím.
Posledním krokem je řazení v SQL před vytvořením výsledků. Concat nezachová pořadí argumentů. Chcete-li zajistit odpovídající řazení, je nutné explicitně uspořádat výsledky Concat.
Protíná, s výjimkou, Sjednocení
Tyto Intersect metody Except jsou dobře definované pouze u sad. Sémantika více sad není definována.
Metoda Union je definována pro více sad jako neuspořádané zřetězení více sad (účinně výsledek klauzule UNION ALL v SQL).
Vezměte, přeskočte
Take a Skip metody jsou dobře definované pouze pro seřazené sady. Sémantika pro neuspořádané sady nebo více sad není definována.
Poznámka:
Take a Skip mají určitá omezení, pokud se používají v dotazech na SQL Server 2000. Další informace naleznete v části Přeskočit a přijmout výjimky v SQL Serveru 2000 v řešení potíží.
Kvůli omezením řazení v SQL se LINQ to SQL pokusí přesunout pořadí argumentů těchto metod na výsledek metody. Představte si například následující dotaz LINQ to SQL:
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
Vygenerovaný kód SQL pro tento kód přesune pořadí na konec následujícím způsobem:
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]
Je zřejmé, že všechna zadaná řazení musí být konzistentní, když Take jsou Skip zřetězený dohromady. V opačném případě jsou výsledky nedefinované.
Obě Take a Skip jsou dobře definované pro nezáporné konstantní celočíselné argumenty založené na specifikaci standardního operátoru dotazu.
Operátory bez překladu
LinQ to SQL nepřekládá následující metody. Nejběžnějším důvodem je rozdíl mezi neuspořádanými vícemnožinami a sekvencemi.
Operátory | Odůvodnění |
---|---|
TakeWhile, SkipWhile | Dotazy SQL pracují s více sadami, ne na sekvencích. ORDER BY musí být poslední klauzule použitá na výsledky. Z tohoto důvodu neexistuje pro tyto dvě metody žádný překlad pro obecné účely. |
Reverse | Překlad této metody je možné pro seřazenou sadu, ale v současné době není přeložen jazykem LINQ do SQL. |
Last, LastOrDefault | Překladtěchtoch metod je možné pro seřazenou sadu, ale není v současné době přeložen jazykem LINQ do SQL. |
ElementAt, ElementAtOrDefault | Dotazy SQL pracují s více sadami, ne s indexovatelnými sekvencemi. |
DefaultIfEmpty (přetížení s výchozí arg) | Obecně platí, že výchozí hodnotu nelze zadat pro libovolnou řazenou kolekci členů. Hodnoty null pro řazené kolekce členů jsou v některých případech možné prostřednictvím vnějších spojení. |
Překlad výrazů
Sémantika Null
LINQ to SQL neukládá sémantiku porovnání null pro SQL. Relační operátory se syntakticky překládají na jejich ekvivalenty SQL. Z tohoto důvodu sémantika odráží sémantiku SQL definovanou nastavením serveru nebo připojení. Například dvě hodnoty null jsou považovány za nerovné v rámci výchozího nastavení SQL Serveru, ale můžete změnit nastavení pro změnu sémantiky. LINQ to SQL při překladu dotazů nebere v úvahu nastavení serveru.
Porovnání s hodnotou null literálu se přeloží na příslušnou verzi SQL (is null
nebo is not null
).
Hodnota null
kolace je definována SQL Serverem. LINQ to SQL nemění kolaci.
Souhrny
Agregační metoda Sum Operátor standardního dotazu se vyhodnotí jako nula pro prázdnou sekvenci nebo pro sekvenci, která obsahuje pouze hodnoty null. V LINQ to SQL se sémantika SQL nezmění a Sum vyhodnotí se null
místo nuly pro prázdnou sekvenci nebo pro sekvenci, která obsahuje pouze hodnoty null.
Omezení SQL u průběžných výsledků platí pro agregace v LINQ to SQL. Sum 32bitové celočíselné množství se nevypočítá pomocí 64bitových výsledků. K přetečení může dojít u překladu SumLINQ to SQL , i když implementace standardního operátoru dotazu nezpůsobí přetečení odpovídající sekvence v paměti.
Podobně se překlad LINQ to SQL Average celočíselných hodnot vypočítá jako , integer
ne jako double
.
Argumenty entity
LINQ to SQL umožňuje použití typů entit v metodách GroupBy a OrderBy metodách. Při překladu těchto operátorů je použití argumentu typu považováno za ekvivalent pro určení všech členů tohoto typu. Například následující kód je ekvivalentní:
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})
Rovníkové / srovnatelné argumenty
Při implementaci následujících metod je vyžadována rovnost argumentů:
LINQ to SQL podporuje rovnost a porovnání pro ploché argumenty, ale ne pro argumenty, které jsou nebo obsahují sekvence. Plochý argument je typ, který lze mapovat na řádek SQL. Projekce jednoho nebo více typů entit, které lze staticky určit, že neobsahují sekvenci, se považuje za plochý argument.
Tady jsou příklady plochých 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})
Tady jsou příklady nerovných (hierarchických) 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)
Překlad funkcí jazyka Visual Basic
Následující pomocné funkce používané kompilátorem jazyka Visual Basic jsou přeloženy do odpovídajících operátorů a funkcí SQL:
CompareString
DateTime.Compare
Decimal.Compare
IIf (in Microsoft.VisualBasic.Interaction)
Metody převodu:
ToBoolean
ToSByte
ToByte
ToChar
ToCharArrayRankOne
ToDate
ToDecimal
ToDouble
ToInteger
ToUInteger
ToLong
ToULong
ToShort
ToUShort
ToSingle
ToString
Podpora dědičnosti
Omezení mapování dědičnosti
Další informace naleznete v tématu Postupy: Mapování hierarchií dědičnosti.
Dědičnost v dotazech
Přetypování jazyka C# se podporuje pouze v projekci. Přetypování, která se používají jinde, se nepřeloží a ignorují se. Kromě názvů funkcí SQL provádí SQL pouze ekvivalent modulu CLR (Common Language Runtime). Convert To znamená, že SQL může změnit hodnotu jednoho typu na jiný. Neexistuje žádný ekvivalent přetypování CLR, protože neexistuje žádný koncept reinterpretace stejných bitů jako ty z jiného typu. Proto přetypování jazyka C# funguje jenom místně. Není vzdálený.
Operátory is
a as
a GetType
metoda nejsou omezeny na Select
operátor. Dají se použít také v jiných operátorech dotazů.
Podpora SQL Serveru 2008
Počínaje rozhraním .NET Framework 3.5 SP1 podporuje LINQ to SQL mapování na nové typy data a času zavedené s SQL Serverem 2008. Existují ale určitá omezení pro operátory dotazů LINQ to SQL, které můžete použít při použití s hodnotami namapovanými na tyto nové typy.
Nepodporované operátory dotazů
Následující operátory dotazu nejsou podporovány u hodnot mapovaných na nové typy data a času SQL Serveru: DATETIME2
, DATE
, TIME
a DATETIMEOFFSET
.
Aggregate
Average
LastOrDefault
OfType
Sum
Další informace o mapování na tyto typy data a času SQL Serveru naleznete v tématu MAPOVÁNÍ typů SQL-CLR.
Podpora SQL Serveru 2005
LINQ to SQL nepodporuje následující funkce SYSTÉMU SQL Server 2005:
Uložené procedury napsané pro SQL CLR
Uživatelem definovaný typ.
Funkce dotazu XML.
Podpora SQL Serveru 2000
Následující omezení SYSTÉMU SQL Server 2000 (ve srovnání s Microsoft SQL Serverem 2005) ovlivňují podporu LINQ to SQL.
Křížové použití a vnější operátory použití
Tyto operátory nejsou v SYSTÉMU SQL Server 2000 k dispozici. LINQ to SQL se pokusí řadu přepisů nahradit odpovídajícími spojeními.
Cross Apply
a Outer Apply
jsou generovány pro navigace relací. Sada dotazů, pro které jsou takové přepisy možné, není dobře definovaná. Z tohoto důvodu je minimální sada dotazů podporovaných pro SQL Server 2000 sada, která nezahrnuje navigaci relací.
text / ntext
Datové typy text
/ ntext
nelze použít v určitých operacích varchar(max)
/ nvarchar(max)
dotazů, které jsou podporovány microsoft SQL Serverem 2005.
Pro toto omezení není k dispozici žádné řešení. Konkrétně nelze použít Distinct()
žádný výsledek, který obsahuje členy mapované na text
sloupce nebo ntext
sloupce.
Chování aktivované vnořenými dotazy
Pořadač SQL Serveru 2000 (až SP4) obsahuje některé idiosyncrasy, které se aktivují vnořenými dotazy. Sada dotazů SQL, které tyto idiosyncrasy aktivují, není dobře definovaná. Z tohoto důvodu nelze definovat sadu dotazů LINQ to SQL, které by mohly způsobit výjimky SQL Serveru.
Přeskočení a převzetí operátorů
Take a Skip mají určitá omezení, pokud se používají v dotazech na SQL Server 2000. Další informace naleznete v části Přeskočit a přijmout výjimky v SQL Serveru 2000 v řešení potíží.
Materializace objektů
Materializace vytváří objekty CLR z řádků vrácených jedním nebo více dotazy SQL.
Následující volání se spouští místně jako součást materializace:
Konstruktory
ToString
metody v projekcíchPřetypování typů v projekcích
Metody, které následují za metodou AsEnumerable , se spouští místně. Tato metoda nezpůsobí okamžité spuštění.
Můžete použít
struct
jako návratový typ výsledku dotazu nebo jako člena typu výsledku. Entity musí být třídy. Anonymní typy jsou materializovány jako instance třídy, ale pojmenované struktury (jiné než entity) lze použít v projekci.Člen návratového typu výsledku dotazu může být typu IQueryable<T>. Je materializován jako místní kolekce.
Následující metody způsobují okamžitou materializaci sekvence, na kterou se metody použijí: