LINQ to SQL은 표준 쿼리 연산자를 SQL 명령으로 변환합니다. 데이터베이스의 쿼리 프로세서는 SQL 변환의 실행 의미 체계를 결정합니다.
표준 쿼리 연산자는 시퀀스에 대해 정의됩니다. 시퀀스는 순서가 지정 되고 시퀀스의 각 요소에 대한 참조 ID를 사용합니다. 자세한 내용은 표준 쿼리 연산자 개요(C#) 또는 표준 쿼리 연산자 개요(Visual Basic)참조하세요.
SQL은 주로 순서가 지정되지 않은 값 집합을 처리합니다. 순서 지정은 일반적으로 중간 결과가 아닌 쿼리의 최종 결과에 적용되는 명시적으로 명시된 후처리 작업입니다. ID는 값으로 정의됩니다. 이러한 이유로 SQL 쿼리는 집합 대신 다중 집합(모음)을 처리하는 것으로 이해됩니다.
다음 단락에서는 LINQ to SQL용 SQL Server 공급자에 대한 표준 쿼리 연산자와 해당 SQL 번역 간의 차이점을 설명합니다.
운영자 지원
Concat
이 Concat 메서드는 수신기의 순서와 인수 순서가 동일한 순서가 지정된 다중 집합에 대해 정의됩니다.
Concat
UNION ALL
은 다중 집합과 일반 순서를 기준으로 작동합니다.
마지막 단계는 결과가 생성되기 전에 SQL에서 정렬하는 것입니다. Concat 는 인수의 순서를 유지하지 않습니다. 적절한 순서를 보장하려면 .의 Concat결과를 명시적으로 정렬해야 합니다.
교집합, 제외, 합집합
및 Intersect 메서드는 Except 집합에서만 잘 정의됩니다. 다중 세트의 의미 체계는 정의되지 않습니다.
이 Union 메서드는 다중 세트의 정렬되지 않은 연결(SQL의 UNION ALL 절 결과)으로 다중 세트에 대해 정의됩니다.
가져가기, 건너뛰기
Take 및 Skip 메서드는 순서가 지정된 집합에 대해서만 잘 정의됩니다. 순서가 지정되지 않은 집합 또는 다중 세트에 대한 의미 체계는 정의되지 않습니다.
비고
Take와 Skip는 SQL Server 2000에 대한 쿼리에서 사용될 때 특정 제한 사항이 있습니다. 자세한 내용은 문제 해결의 "SQL Server 2000에서 예외 건너뛰기 및 예외 처리" 항목을 참조하세요.
SQL의 순서 지정에 대한 제한 사항 때문에 LINQ to SQL은 이러한 메서드의 인수 순서를 메서드의 결과로 이동하려고 합니다. 예를 들어 다음 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
이 코드에 대해 생성된 SQL은 다음과 같이 순서를 끝으로 이동합니다.
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]
지정된 모든 순서는 Take와 Skip가 함께 연결될 때 일관성이 있어야 한다는 것이 분명해집니다. 그렇지 않으면 결과가 정의되지 않습니다.
Take와 Skip 둘 다 표준 쿼리 연산자 사양에 따라 음이 아닌 정수 인수에 대해 잘 정의되어 있습니다.
번역이 없는 연산자
LINQ에서 SQL로 변환되지 않는 메서드는 다음과 같습니다. 가장 일반적인 이유는 순서가 지정되지 않은 다중 집합과 시퀀스의 차이입니다.
운영자 | 근거 |
---|---|
TakeWhile, SkipWhile | SQL 쿼리는 시퀀스가 아닌 다중 집합에서 작동합니다.
ORDER BY 는 결과에 적용되는 마지막 절이어야 합니다. 이러한 이유로 이러한 두 메서드에 대한 범용 번역은 없습니다. |
Reverse | 이 메서드의 변환은 정렬된 집합에 대해 가능하지만 현재 LINQ to SQL에서 변환되지 않습니다. |
Last, LastOrDefault | 이러한 메서드의 변환은 순서가 지정된 집합에 대해 가능하지만 현재 LINQ에서 SQL로 변환되지 않습니다. |
ElementAt, ElementAtOrDefault | SQL 쿼리는 인덱싱 가능한 시퀀스가 아닌 다중 집합에서 작동합니다. |
DefaultIfEmpty (기본 인수를 사용하는 오버로드) | 일반적으로 임의의 튜플에 대해 기본값을 지정할 수 없습니다. 튜플에 대한 Null 값은 경우에 따라 외부 조인을 통해 가능합니다. |
표현 번역
Null 의미론
LINQ to SQL은 SQL에 null 비교 의미 체계를 적용하지 않습니다. 비교 연산자는 해당 SQL 등가물로 구문적으로 변환됩니다. 이러한 이유로 의미 체계는 서버 또는 연결 설정에 의해 정의된 SQL 의미 체계를 반영합니다. 예를 들어 두 null 값은 기본 SQL Server 설정에서 같지 않은 것으로 간주되지만 설정을 변경하여 의미 체계를 변경할 수 있습니다. LINQ to SQL은 쿼리를 변환할 때 서버 설정을 고려하지 않습니다.
리터럴 null과의 비교는 적절한 SQL 버전(is null
또는 is not null
)으로 변환됩니다.
데이터 정렬의 null
값은 SQL Server에 의해 정의됩니다. LINQ to SQL은 데이터 정렬을 변경하지 않습니다.
집합체
표준 쿼리 연산자 집계 메서드 Sum 는 빈 시퀀스 또는 null만 포함된 시퀀스에 대해 0으로 평가됩니다. LINQ to SQL에서 SQL의 의미 체계는 변경되지 않으며, 빈 시퀀스 또는 null만 포함된 시퀀스의 경우 0이 아닌 Sum으로 평가됩니다.
중간 결과에 대한 SQL 제한 사항은 LINQ to SQL의 집계에 적용됩니다. 32비트 정수 수량은 Sum 64비트 결과를 사용하여 계산되지 않습니다. 표준 쿼리 연산자 구현으로 인해 해당 메모리 내 시퀀스에 대한 오버플로가 발생하지 않더라도 LINQ to SQL 변환 Sum에 오버플로가 발생할 수 있습니다.
마찬가지로, 정수 값의 Average LINQ to SQL 변환은 integer
가 아니라 double
로 계산됩니다.
엔터티 매개변수
LINQ to SQL을 사용하면 엔터티 형식을 GroupBy 및 OrderBy 메서드에서 사용할 수 있습니다. 이러한 연산자의 변환에서 형식의 인수 사용은 해당 형식의 모든 멤버를 지정하는 것과 동일한 것으로 간주됩니다. 예를 들어 다음 코드는 동일합니다.
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})
적정/비교 가능한 인수
다음 메서드의 구현에는 인수의 같음이 필요합니다.
LINQ to SQL은 플랫 인수에 대한 같음 및 비교를 지원하지만 시퀀스가 있거나 포함된 인수는 지원하지 않습니다. 플랫 인수는 SQL 행에 매핑할 수 있는 형식입니다. 시퀀스를 포함하지 않도록 정적으로 확인할 수 있는 하나 이상의 엔터티 형식의 프로젝션은 플랫 인수로 간주됩니다.
다음은 플랫 인수의 예입니다.
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})
다음은 플랫이 아닌(계층적) 인수의 예입니다.
// 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 함수 변환
Visual Basic 컴파일러에서 사용되는 다음 도우미 함수는 해당 SQL 연산자 및 함수로 변환됩니다.
CompareString
DateTime.Compare
Decimal.Compare
IIf (in Microsoft.VisualBasic.Interaction)
변환 방법:
ToBoolean
ToSByte
ToByte
ToChar
ToCharArrayRankOne
ToDate
ToDecimal
ToDouble
ToInteger
ToUInteger
ToLong
ToULong
ToShort
ToUShort
ToSingle
ToString
상속 지원
상속 매핑 제한
자세한 내용은 방법: 상속 계층 구조 매핑을 참조하세요.
쿼리의 상속
C# 캐스트는 프로젝션에서만 지원됩니다. 다른 곳에서 사용되는 캐스트는 번역되지 않으며 무시됩니다. SQL 함수 이름 외에 SQL은 CLR(공용 언어 런타임) Convert과 동등한 작업만 수행합니다. 즉, SQL은 한 형식의 값을 다른 형식으로 변경할 수 있습니다. 동일한 비트를 다른 형식으로 재해석하는 개념이 없기 때문에 CLR 캐스트에 해당하는 개념이 없습니다. 따라서 C# 캐스트는 로컬에서만 작동합니다. 원격 제어가 아닙니다.
연산자 is
및 as
와 메서드 GetType
는 Select
연산자에 제한되지 않습니다. 다른 쿼리 연산자에서도 사용할 수 있습니다.
SQL Server 2008 지원
.NET Framework 3.5 SP1부터 LINQ to SQL은 SQL Server 2008에 도입된 새 날짜 및 시간 형식에 대한 매핑을 지원합니다. 그러나 이러한 새 형식에 매핑된 값에 대해 작업할 때 사용할 수 있는 LINQ to SQL 쿼리 연산자에는 몇 가지 제한 사항이 있습니다.
지원되지 않는 쿼리 연산자
새 SQL Server 날짜 및 시간 형식DATETIME2
DATE
TIME
DATETIMEOFFSET
에 매핑된 값에는 다음 쿼리 연산자가 지원되지 않습니다.
Aggregate
Average
LastOrDefault
OfType
Sum
이러한 SQL Server 날짜 및 시간 형식에 매핑하는 방법에 대한 자세한 내용은 SQL-CLR 형식 매핑을 참조하세요.
SQL Server 2005 지원
LINQ to SQL은 다음 SQL Server 2005 기능을 지원하지 않습니다.
SQL CLR용으로 작성된 저장 프로시저입니다.
사용자 정의 형식입니다.
XML 쿼리 기능.
SQL Server 2000 지원
다음 SQL Server 2000 제한 사항(Microsoft SQL Server 2005와 비교)은 LINQ to SQL 지원에 영향을 줍니다.
교차 적용 및 외부 적용 연산자
이러한 연산자는 SQL Server 2000에서 사용할 수 없습니다. LINQ to SQL은 일련의 재작성을 시도하여 적절한 조인으로 대체합니다.
관계 내비게이션을 위해 Cross Apply
및 Outer Apply
가 생성됩니다. 이러한 다시 쓰기가 가능한 쿼리 집합은 잘 정의되지 않았습니다. 이러한 이유로 SQL Server 2000에 대해 지원되는 최소한의 쿼리 집합은 관계 탐색을 포함하지 않는 집합입니다.
text / ntext
Microsoft SQL Server 2005에서 지원하는 text
/ ntext
에 대한 특정 쿼리 작업에서는 데이터 형식 varchar(max)
/ nvarchar(max)
을 사용할 수 없습니다.
이 제한에 대한 해결 방법은 없습니다. 특히 Distinct()
또는 text
열에 매핑된 멤버가 포함된 결과에는 ntext
을(를) 사용할 수 없습니다.
중첩된 쿼리에 의해 트리거되는 동작
SQL Server 2000(SP4를 통해) 바인더에는 중첩된 쿼리에 의해 트리거되는 몇 가지 특이성이 있습니다. 이러한 특이성을 트리거하는 SQL 쿼리 집합은 잘 정의되지 않았습니다. 따라서 SQL Server 예외를 일으킬 수 있는 LINQ to SQL 쿼리 집합을 정의할 수 없습니다.
건너뛰기 및 가져오기 연산자
Take와 Skip는 SQL Server 2000에 대한 쿼리에서 사용될 때 특정 제한 사항이 있습니다. 자세한 내용은 문제 해결의 "SQL Server 2000에서 예외 건너뛰기 및 예외 처리" 항목을 참조하세요.
개체 구체화
구체화는 하나 이상의 SQL 쿼리에서 반환되는 행에서 CLR 개체를 만듭니다.
다음 호출은 구체화의 일부로 로컬로 실행됩니다 .
생성자
ToString
프로젝션의 메서드프로젝션의 형식 캐스트
메서드를 AsEnumerable 따르는 메서드는 로컬로 실행됩니다. 이 메서드는 즉시 실행되지 않습니다.
쿼리 결과의 반환 형식 또는 결과 형식의 멤버로 사용할
struct
수 있습니다. 엔터티는 클래스여야 합니다. 익명 형식은 클래스 인스턴스로 구체화되지만 명명된 구조체(비 엔터티)는 프로젝션에 사용할 수 있습니다.쿼리 결과의 반환 형식 멤버는 형식 IQueryable<T>일 수 있습니다. 로컬 컬렉션으로 구체화됩니다.
다음 메서드는 메서드가 적용되는 시퀀스를 즉시 구체화 합니다.