Translacja standardowego operatora zapytania
LinQ to SQL tłumaczy standardowe operatory zapytań na polecenia SQL. Procesor zapytań bazy danych określa semantyka wykonywania tłumaczenia SQL.
Standardowe operatory zapytań są definiowane względem sekwencji. Sekwencja jest uporządkowana i opiera się na tożsamości referencyjnej dla każdego elementu sekwencji. Aby uzyskać więcej informacji, zobacz Omówienie standardowych operatorów zapytań (C#) lub Standardowe operatory zapytań — omówienie (Visual Basic).
Język SQL dotyczy przede wszystkim nieurządzanych zestawów wartości. Porządkowanie to zazwyczaj jawnie określona operacja przetwarzania końcowego, która jest stosowana do końcowego wyniku zapytania, a nie do wyników pośrednich. Tożsamość jest definiowana przez wartości. Z tego powodu zapytania SQL są zrozumiałe, aby radzić sobie z wieloma zestawami (workami) zamiast zestawów.
W poniższych akapitach opisano różnice między standardowymi operatorami zapytań a ich tłumaczeniem SQL dla dostawcy programu SQL Server dla linQ to SQL.
Obsługa operatora
Concat
Metoda jest definiowana Concat dla uporządkowanych wielozestawów, w których kolejność odbiornika i kolejność argumentu są takie same. Concat działa tak jak UNION ALL
w przypadku wielu zestawów, po których następuje wspólna kolejność.
Ostatnim krokiem jest kolejność w języku SQL przed rozpoczęciem tworzenia wyników. Concat nie zachowuje kolejności argumentów. Aby zapewnić odpowiednią kolejność, należy jawnie uporządkować wyniki .Concat
Przecięcie, z wyjątkiem unii
Metody Intersect i Except są dobrze zdefiniowane tylko w zestawach. Semantyka dla wielu zestawów jest niezdefiniowana.
Metoda Union jest definiowana dla wielu zestawów jako nieurządkowanego łączenia wielozestawów (skutecznie wynik klauzuli UNION ALL w języku SQL).
Weź, pomiń
Take metody i Skip są dobrze zdefiniowane tylko dla uporządkowanych zestawów. Semantyka zestawów nieurządzanych lub wielozestawów jest niezdefiniowana.
Uwaga
Take i Skip mają pewne ograniczenia, gdy są używane w zapytaniach względem programu SQL Server 2000. Aby uzyskać więcej informacji, zobacz wpis "Pomiń i weź wyjątki w programie SQL Server 2000" w temacie Rozwiązywanie problemów.
Ze względu na ograniczenia dotyczące porządkowania w języku SQL linQ to SQL próbuje przenieść kolejność argumentu tych metod do wyniku metody. Rozważmy na przykład następujące zapytanie 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
Wygenerowany kod SQL przenosi kolejność na koniec w następujący sposób:
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]
Staje się oczywiste, że wszystkie określone kolejność muszą być spójne, gdy Take i Skip są połączone ze sobą. W przeciwnym razie wyniki są niezdefiniowane.
Oba Take argumenty i Skip są dobrze zdefiniowane dla argumentów nieujemnych, stałych całkowitych na podstawie standardowej specyfikacji operatora zapytania.
Operatory bez tłumaczenia
Następujące metody nie są tłumaczone przez LINQ na język SQL. Najczęstszą przyczyną jest różnica między nieurządkowanym wieloma zestawami i sekwencjami.
Operatory | Uzasadnienie |
---|---|
TakeWhile, SkipWhile | Zapytania SQL działają na wielu zestawach, a nie na sekwencjach. ORDER BY musi być ostatnią klauzulą zastosowaną do wyników. Z tego powodu nie ma tłumaczenia ogólnego przeznaczenia dla tych dwóch metod. |
Reverse | Tłumaczenie tej metody jest możliwe dla uporządkowanego zestawu, ale nie jest obecnie tłumaczone przez LINQ to SQL. |
Last, LastOrDefault | Tłumaczenie tych metod jest możliwe dla uporządkowanego zestawu, ale nie jest obecnie tłumaczone przez LINQ to SQL. |
ElementAt, ElementAtOrDefault | Zapytania SQL działają na wielu zestawach, a nie w sekwencjach z możliwością indeksowania. |
DefaultIfEmpty (przeciążenie z wartością domyślną arg) | Ogólnie rzecz biorąc, nie można określić wartości domyślnej dla dowolnej krotki. Wartości null krotki są możliwe w niektórych przypadkach za pośrednictwem sprzężeń zewnętrznych. |
Tłumaczenie wyrażeń
Semantyka wartości null
LinQ to SQL nie nakłada semantyki porównania wartości null na język SQL. Operatory porównania są syntactycznie tłumaczone na ich odpowiedniki SQL. Z tego powodu semantyka odzwierciedla semantykę SQL zdefiniowaną przez ustawienia serwera lub połączenia. Na przykład dwie wartości null są traktowane jako nierówne w domyślnych ustawieniach programu SQL Server, ale można zmienić ustawienia, aby zmienić semantyka. LinQ to SQL nie uwzględnia ustawień serwera podczas tłumaczenia zapytań.
Porównanie z literałem null jest tłumaczone na odpowiednią wersję SQL (is null
lub is not null
).
Wartość sortowania jest definiowana null
przez program SQL Server. LinQ to SQL nie zmienia sortowania.
Agregacje
Metoda Sum agregowania operatora zapytania standardowego oblicza wartość zero dla pustej sekwencji lub dla sekwencji zawierającej tylko wartości null. W linQ to SQL semantyka sql pozostaje niezmieniona i Sum oblicza wartość null
zamiast zera dla pustej sekwencji lub dla sekwencji zawierającej tylko wartości null.
Ograniczenia języka SQL dotyczące wyników pośrednich mają zastosowanie do agregacji w linQ to SQL. Sum 32-bitowe ilości całkowite nie są obliczane przy użyciu wyników 64-bitowych. Przepełnienie może wystąpić w przypadku tłumaczenia SumLINQ to SQL klasy , nawet jeśli implementacja standardowego operatora zapytania nie powoduje przepełnienia odpowiedniej sekwencji w pamięci.
Podobnie translacja Average LINQ to SQL wartości całkowitych jest obliczana jako integer
, a nie jako double
.
Argumenty jednostki
LINQ to SQL umożliwia korzystanie z typów jednostek w metodach GroupBy i OrderBy . W tłumaczeniu tych operatorów użycie argumentu typu jest uważane za równoważne określeniu wszystkich elementów członkowskich tego typu. Na przykład następujący kod jest równoważny:
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})
Equatable /porównywalne argumenty
Równość argumentów jest wymagana w implementacji następujących metod:
LinQ to SQL obsługuje równość i porównanie argumentów prostych , ale nie dla argumentów, które są lub zawierają sekwencje. Prosty argument to typ, który można zamapować na wiersz SQL. Projekcja jednego lub większej liczby typów jednostek, które mogą być statycznie określone, aby nie zawierała sekwencji, jest traktowana jako prosty argument.
Poniżej przedstawiono przykłady prostych argumentów:
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})
Poniżej przedstawiono przykłady argumentów innych niż płaskie (hierarchiczne):
// 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)
Tłumaczenie funkcji Visual Basic
Następujące funkcje pomocnicze, które są używane przez kompilator języka Visual Basic, są tłumaczone na odpowiednie operatory i funkcje SQL:
CompareString
DateTime.Compare
Decimal.Compare
IIf (in Microsoft.VisualBasic.Interaction)
Metody konwersji:
ToBoolean
ToSByte
ToByte
ToChar
ToCharArrayRankOne
ToDate
ToDecimal
ToDouble
ToInteger
ToUInteger
ToLong
ToULong
ToShort
ToUShort
ToSingle
ToString
Obsługa dziedziczenia
Ograniczenia mapowania dziedziczenia
Aby uzyskać więcej informacji, zobacz Jak mapować hierarchie dziedziczenia.
Dziedziczenie w zapytaniach
Rzutowania w języku C# są obsługiwane tylko w projekcji. Rzuty, które są używane gdzie indziej, nie są tłumaczone i są ignorowane. Oprócz nazw funkcji SQL program SQL naprawdę wykonuje tylko odpowiednik środowiska uruchomieniowego języka wspólnego (CLR). Convert Oznacza to, że usługa SQL może zmienić wartość jednego typu na inny. Nie ma odpowiednika rzutowania CLR, ponieważ nie ma pojęcia ponownego interpretowania tych samych bitów co bity innego typu. Dlatego rzutowanie w języku C# działa tylko lokalnie. Nie jest zdalna.
Operatory is
i as
, i GetType
metoda nie są ograniczone do Select
operatora. Mogą być one również używane w innych operatorach zapytań.
Obsługa programu SQL Server 2008
Począwszy od programu .NET Framework 3.5 SP1, LINQ to SQL obsługuje mapowanie na nowe typy dat i godzin wprowadzone w programie SQL Server 2008. Istnieją jednak pewne ograniczenia dotyczące operatorów zapytań LINQ to SQL, których można użyć podczas działania względem wartości zamapowanych na te nowe typy.
Nieobsługiwane operatory zapytań
Następujące operatory zapytań nie są obsługiwane w przypadku wartości zamapowanych na nowe typy dat i godzin programu SQL Server: DATETIME2
, , DATE
TIME
i DATETIMEOFFSET
.
Aggregate
Average
LastOrDefault
OfType
Sum
Aby uzyskać więcej informacji na temat mapowania na te typy dat i godzin programu SQL Server, zobacz Sql-CLR Type Mapping (Mapowanie typów SQL-CLR).
Obsługa programu SQL Server 2005
LINQ to SQL nie obsługuje następujących funkcji programu SQL Server 2005:
Procedury składowane napisane dla środowiska SQL CLR.
Typ zdefiniowany przez użytkownika.
Funkcje zapytań XML.
Obsługa programu SQL Server 2000
Następujące ograniczenia programu SQL Server 2000 (w porównaniu z programem Microsoft SQL Server 2005) mają wpływ na obsługę linQ to SQL.
Operatory stosowania krzyżowego i zewnętrznego
Te operatory nie są dostępne w programie SQL Server 2000. LINQ to SQL próbuje wykonać serię ponownych pisania, aby zastąpić je odpowiednimi sprzężeniami.
Cross Apply
i Outer Apply
są generowane dla nawigacji relacji. Zestaw zapytań, dla których takie ponowne zapisywanie jest możliwe, nie jest dobrze zdefiniowany. Z tego powodu minimalny zestaw zapytań obsługiwanych dla programu SQL Server 2000 to zestaw, który nie obejmuje nawigacji relacji.
tekst/ntekst
Typy text
/ ntext
danych nie mogą być używane w niektórych operacjach zapytań względem varchar(max)
/ nvarchar(max)
programu , które są obsługiwane przez program Microsoft SQL Server 2005.
Brak możliwości rozwiązania dla tego ograniczenia. W szczególności nie można użyć Distinct()
żadnego wyniku zawierającego elementy członkowskie mapowane na text
kolumny lub ntext
.
Zachowanie wyzwalane przez zagnieżdżone zapytania
Binder programu SQL Server 2000 (do SP4) zawiera pewne idiosyncrasy wyzwalane przez zagnieżdżone zapytania. Zestaw zapytań SQL, które wyzwala te idiosyncrasies, nie jest dobrze zdefiniowany. Z tego powodu nie można zdefiniować zestawu zapytań LINQ to SQL, które mogą powodować wyjątki programu SQL Server.
Pomijanie i przejmowanie operatorów
Take i Skip mają pewne ograniczenia, gdy są używane w zapytaniach względem programu SQL Server 2000. Aby uzyskać więcej informacji, zobacz wpis "Pomiń i weź wyjątki w programie SQL Server 2000" w temacie Rozwiązywanie problemów.
Materializacja obiektu
Materializacja tworzy obiekty CLR z wierszy zwracanych przez co najmniej jedno zapytanie SQL.
Następujące wywołania są wykonywane lokalnie w ramach materializacji:
Konstruktory
ToString
metody projekcjiRzutowanie typu w projekcjach
Metody zgodne z AsEnumerable metodą są wykonywane lokalnie. Ta metoda nie powoduje natychmiastowego wykonania.
Możesz użyć
struct
jako zwracanego typu wyniku zapytania lub jako elementu członkowskiego typu wyników. Jednostki muszą być klasami. Typy anonimowe są zmaterializowane jako wystąpienia klas, ale w projekcji można używać nazwanych struktur (innych niż jednostki).Element członkowski zwracanego typu wyniku zapytania może mieć typ IQueryable<T>. Jest zmaterializowany jako kolekcja lokalna.
Następujące metody powodują natychmiastową materializację sekwencji stosowanej do metod: