LINQ(Language-Integrated Query)

LINQ(Language-Integrated Query)는 C# 언어에 직접 쿼리 기능을 통합하는 방식을 기반으로 하는 기술 집합 이름입니다. 일반적으로 데이터에 대한 쿼리는 컴파일 시간의 형식 검사나 IntelliSense 지원 없이 간단한 문자열로 표현됩니다. 또한 SQL 데이터베이스, XML 문서, 다양한 웹 서비스 등의 각 데이터 소스 형식에 대해 서로 다른 쿼리 언어를 배워야 합니다. LINQ에서 쿼리는 클래스, 메서드 및 이벤트와 마찬가지로 최고의 언어 구문입니다.

쿼리를 작성할 때 LINQ에서 가장 눈에 띄는 "언어 통합" 부분은 쿼리 식입니다. 쿼리 식은 선언적 쿼리 구문으로 작성됩니다. 쿼리 구문을 사용하면 최소한의 코드로 데이터 원본에 대한 필터링, 정렬 및 그룹화 작업을 수행할 수 있습니다. 동일한 쿼리 식 패턴을 사용하여 모든 형식의 데이터 원본에서 데이터를 쿼리하고 변환할 수 있습니다.

다음 예제에서는 전체 쿼리 작업을 보여줍니다. 전체 작업에는 데이터 소스 만들기, 쿼리 식 정의 및 foreach 문의 쿼리 실행이 포함됩니다.

// Specify the data source.
int[] scores = [97, 92, 81, 60];

// Define the query expression.
IEnumerable<int> scoreQuery =
    from score in scores
    where score > 80
    select score;

// Execute the query.
foreach (var i in scoreQuery)
{
    Console.Write(i + " ");
}

// Output: 97 92 81

이전 예제를 컴파일하려면 using 지시문 using System.Linq;를 추가해야 할 수도 있습니다. 최신 버전의 .NET에서는 암시적 using을 사용하여 이 지시문을 전역 using으로 추가합니다. 이전 버전에서는 원본에 추가해야 합니다.

쿼리 식 개요

  • 쿼리 식은 LINQ 사용 데이터 원본에서 데이터를 쿼리하고 변환합니다. 예를 들어 단일 쿼리는 SQL 데이터베이스에서 데이터를 검색하고 XML 스트림을 출력으로 생성할 수 있습니다.
  • 쿼리 식은 친숙한 C# 언어 구문을 많이 사용하므로 쉽게 읽을 수 있습니다.
  • 쿼리 식의 변수는 모두 강력한 형식입니다.
  • 예를 들어 foreach 문에서 쿼리 변수를 반복할 때까지 쿼리는 실행되지 않습니다.
  • 컴파일 시간에 쿼리 식은 C# 사양에 정의된 규칙에 따라 표준 쿼리 연산자 메서드 호출로 변환됩니다. 쿼리 구문을 사용하여 표현할 수 있는 모든 쿼리는 메서드 구문으로도 표현할 수 있습니다. 경우에 따라 쿼리 구문이 더 읽기 쉽고 간결합니다. 다른 경우에는 메서드 구문이 더 읽기 쉽습니다. 두 가지 형식 간에 의미 체계 또는 성능의 차이가 없습니다. 자세한 내용은 C# 언어 사양표준 쿼리 연산자 개요를 참조하세요.
  • Count 또는 Max와 같은 일부 쿼리 작업은 해당하는 쿼리 식 절이 없으므로 메서드 호출로 표현해야 합니다. 메서드 구문을 다양한 방법으로 쿼리 구문에 조합할 수 있습니다.
  • 쿼리 식은 쿼리가 적용되는 형식에 따라 식 트리 또는 대리자로 컴파일될 수 있습니다. IEnumerable<T> 쿼리는 대리자로 컴파일됩니다. IQueryableIQueryable<T> 쿼리는 식 트리로 컴파일됩니다. 자세한 내용은 식 트리를 참조하세요.

데이터 원본의 LINQ 쿼리를 사용하도록 설정하는 방법

메모리 내 데이터

메모리 내 데이터의 LINQ 쿼리를 사용하도록 설정하는 방법에는 두 가지가 있습니다. 데이터가 IEnumerable<T>을 구현하는 형식인 경우 LINQ to Objects를 사용하여 데이터를 쿼리합니다. IEnumerable<T> 인터페이스를 구현하여 열거형을 사용하도록 설정하는 것이 적절하지 않은 경우 해당 형식 또는 해당 형식에 대한 확장 메서드로 LINQ 표준 쿼리 연산자 메서드를 정의합니다. 표준 쿼리 연산자의 사용자 지정 구현에서는 지연된 실행을 사용하여 결과를 반환해야 합니다.

원격 데이터

원격 데이터 소스의 LINQ 쿼리를 사용 설정하는 가장 좋은 방법은 IQueryable<T> 인터페이스를 구현하는 것입니다.

IQueryable LINQ 공급자

IQueryable<T>을 구현하는 LINQ 공급자의 복잡성은 경우에 따라 크게 다릅니다.

덜 복잡한 IQueryable 공급자는 웹 서비스에서 단일 메서드에 액세스할 수 있습니다. 이러한 형식의 공급자는 쿼리에 처리할 특정 정보가 있다고 가정하므로 매우 한정적이며, 대개 단일 결과 형식을 노출하는 폐쇄형 형식 시스템을 갖고 있습니다. 대부분의 쿼리 실행은 로컬에서 수행됩니다. 예를 들어 표준 쿼리 연산자의 Enumerable 구현을 사용하여 실행됩니다. 복잡성이 낮은 공급자는 식 트리에서 쿼리를 나타내는 하나의 메서드 호출 식만 검사하고 쿼리의 나머지 논리는 다른 곳에서 처리되도록 할 수 있습니다.

복잡성이 보통인 IQueryable 공급자는 부분적으로 표현되는 쿼리 언어가 있는 데이터 소스를 대상으로 할 수 있습니다. 웹 서비스를 대상으로 하는 경우 두 개 이상의 웹 서비스 메서드에 액세스하고 쿼리에서 찾는 정보에 따라 호출할 메서드를 선택할 수 있습니다. 복잡성이 보통인 공급자는 복잡성이 낮은 공급자보다 풍부한 형식 시스템을 가질 수 있지만 여전히 고정된 형식 시스템을 유지합니다. 예를 들어 공급자는 순회할 수 있는 일대다 관계가 있는 형식을 노출할 수 있지만 사용자 정의 형식에 대한 매핑 기술은 제공하지 않습니다.

Entity Framework Core 공급자와 같은 복잡한 IQueryable 공급자는 전체 LINQ 쿼리를 SQL과 같은 표현 쿼리 언어로 변환할 수 있습니다. 복잡한 공급자는 쿼리에서 더욱 다양한 질문을 처리할 수 있으므로 더 일반적입니다. 또한 개방형 형식 시스템을 가지므로 사용자 정의 형식을 매핑하는 확장 인프라를 포함해야 합니다. 복잡성이 높은 공급자를 개발하려면 상당한 노력이 필요합니다.