수색…


비고

LINQ는 .NET Framework 버전 3.5에 도입 된 일련의 기능으로 개체 세계와 데이터 세계 사이의 틈을 연결합니다.

일반적으로 데이터에 대한 쿼리는 컴파일 타임이나 IntelliSense 지원에서 형식 검사없이 간단한 문자열로 표현됩니다. 또한 SQL 데이터베이스, XML 문서, 다양한 웹 서비스 등 각 데이터 소스 유형에 대해 다른 쿼리 언어를 배워야합니다. LINQ는 C # 및 Visual Basic에서 쿼리를 일급 언어 구문으로 만듭니다. 언어 키워드와 친숙한 연산자를 사용하여 강력한 형식의 개체 컬렉션에 대한 쿼리를 작성합니다.

설정

LINQ에는 .NET 3.5 이상 (또는 LINQBridge를 사용하는 .NET 2.0)이 필요합니다.

아직 추가되지 않은 경우 System.Core에 대한 참조를 추가하십시오.

파일의 맨 위에서 네임 스페이스를 가져옵니다.

  • 기음#
  using System;
  using System.Linq;
  • VB.NET
  Imports System.Linq

LINQ의 다른 조인

다음 예제에서는 다음 샘플을 사용합니다.

List<Product> Products = new List<Product>()
{
  new Product()
  {
    ProductId = 1,
    Name = "Book nr 1",
    Price = 25
  },
  new Product()
  {
    ProductId = 2,
    Name = "Book nr 2",
    Price = 15
  },
  new Product()
  {
    ProductId = 3,
    Name = "Book nr 3",
    Price = 20
  },
};
List<Order> Orders = new List<Order>()
{
  new Order()
  {
    OrderId = 1,
    ProductId = 1,
  },
  new Order()
  {
    OrderId = 2,
    ProductId = 1,
  },
  new Order()
  {
    OrderId = 3,
    ProductId = 2,
  },
  new Order()
  {
    OrderId = 4,
    ProductId = NULL,
  },
};

내부 결합

검색어 구문

var joined = (from p in Products
              join o in Orders on p.ProductId equals o.ProductId
              select new
              {
                o.OrderId,
                p.ProductId,
                p.Name
              }).ToList();

메서드 구문

var joined = Products.Join(Orders, p => p.ProductId, 
                                   o => o.OrderId, 
                                     => new 
                                    { 
                                      OrderId   = o.OrderId, 
                                      ProductId = p.ProductId, 
                                      Name      = p.Name 
                                    })
                     .ToList();

결과:

{ 1, 1, "Book nr 1" },
{ 2, 1, "Book nr 1" },
{ 3, 2, "Book nr 2" }

LEFT OUTER JOIN

var joined = (from p in Products
              join o in Orders on p.ProductId equals o.ProductId into g
              from lj in g.DefaultIfEmpty()
              select new
              {
                //For the empty records in lj, OrderId would be NULL
                OrderId = (int?)lj.OrderId,
                p.ProductId,
                p.Name
              }).ToList();

결과:

{ 1, 1, "Book nr 1" },
{ 2, 1, "Book nr 1" },
{ 3, 2, "Book nr 2" },
{ NULL, 3, "Book nr 3" }

크로스 조인

var joined = (from p in Products
              from o in Orders
              select new
              {
                o.OrderId,
                p.ProductId,
                p.Name
              }).ToList();

결과:

{ 1, 1, "Book nr 1" },
{ 2, 1, "Book nr 1" },
{ 3, 2, "Book nr 2" },
{ NULL, 3, "Book nr 3" },
{ 4, NULL, NULL }

GROUP JOIN

var joined = (from p in Products
              join o in Orders on p.ProductId equals o.ProductId
                into t
              select new
              {
                p.ProductId,
                p.Name,
                Orders = t
              }).ToList();

이제 Propertiesie Orders 연결된 모든 IEnumerable<Order> 가있는 IEnumerable<Order> 포함됩니다.

결과:

{ 1, "Book nr 1", Orders = { 1, 2 } },
{ 2, "Book nr 2", Orders = { 3 } },
{ 3, "Book nr 3", Orders = { } },

여러 조건에 참여하는 방법

단일 조건에 합류 할 때 다음을 사용할 수 있습니다.

join o in Orders 
  on p.ProductId equals o.ProductId

여러 항목에 가입하려면 다음을 사용하십시오.

join o in Orders 
  on new { p.ProductId, p.CategoryId } equals new { o.ProductId, o.CategoryId }

익명 객체가 모두 동일한 속성을 갖고 VB.NET에서 Key 로 표시되어야합니다. VB.NET에서는 여러 Equals 절을 And 구분할 수 있습니다.

Join o In Orders 
  On p.ProductId Equals o.ProductId And p.CategoryId Equals o.CategoryId

쿼리 구문 및 메서드 구문

쿼리 구문과 메서드 구문은 의미 상 동일하지만 많은 사람들이 쿼리 구문을 더 간단하고 쉽게 읽을 수 있습니다. 숫자 컬렉션에서 오름차순으로 정렬 된 모든 짝수 항목을 검색해야한다고 가정 해 봅시다.

기음#:

int[] numbers = { 0, 1, 2, 3, 4, 5, 6 };

// Query syntax:
IEnumerable<int> numQuery1 =
            from num in numbers
            where num % 2 == 0
            orderby num
            select num;

// Method syntax:
IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0).OrderBy(n => n);

VB.NET :

Dim numbers() As Integer = { 0, 1, 2, 3, 4, 5, 6 }

' Query syntax: '
Dim numQuery1 = From num In numbers
                 Where num Mod 2 = 0
                 Select num
                 Order By num

' Method syntax: '
Dim numQuery2 = numbers.where(Function(num) num Mod 2 = 0).OrderBy(Function(num) num)

일부 쿼리 메소드 호출로 표현 되어야 한다는 것을 기억하십시오. 예를 들어, 지정된 조건과 일치하는 요소의 수를 검색하는 쿼리를 표현하려면 메서드 호출을 사용해야합니다. 또한 소스 순서에서 최대 값을 갖는 요소를 검색하는 조회에 메소드 호출을 사용해야합니다. 따라서 메서드 구문을 사용하여 코드의 일관성을 유지하는 것이 유리할 수 있습니다. 그러나 쿼리 구문 호출 후에 항상 메서드를 적용 할 수 있습니다.

기음#:

int maxNum =
    (from num in numbers
     where num % 2 == 0
     select num).Max();

VB.NET :

Dim maxNum =
    (From num In numbers
     Where num Mod 2 = 0
     Select num).Max();

LINQ 메서드 및 IEnumerable IQueryable 대

IEnumerable<T> 에 대한 LINQ 확장 메서드는 실제 메서드를 1 , 익명 메서드 여부 :

//C#
Func<int,bool> fn = x => x > 3;
var list = new List<int>() {1,2,3,4,5,6};
var query = list.Where(fn);

'VB.NET
Dim fn = Function(x As Integer) x > 3
Dim list = New List From {1,2,3,4,5,6};
Dim query = list.Where(fn);

또는 명명 된 메소드 (명시 적으로 클래스의 일부로 정의 된 메소드) :

//C#
class Program {
    bool LessThan4(int x) {
        return x < 4;
    }

    void Main() {
        var list = new List<int>() {1,2,3,4,5,6};
        var query = list.Where(LessThan4);
    }
}

'VB.NET
Class Program
    Function LessThan4(x As Integer) As Boolean
        Return x < 4
    End Function
    Sub Main
        Dim list = New List From {1,2,3,4,5,6};
        Dim query = list.Where(AddressOf LessThan4)
    End Sub
End Class

이론적으로 는 메소드의 IL구문 분석하고 메소드 가 수행하려고 시도하는 것을 파악한 후 메모리의 객체가 아닌 모든 기본 데이터 소스에 해당 메소드의 로직을 적용하는 것이 가능합니다. 그러나 일리 파문을 파싱하는 것은 마음이 희미하지 않은 것이 아닙니다.


다행스럽게도 .NET은이 시나리오에서 IQueryable<T> 인터페이스와 System.Linq.Queryable 의 확장 메서드를 제공합니다. 이러한 확장 메서드는 실제 메서드 대신 표현 트리 (코드를 나타내는 데이터 구조)를 사용하여 LINQ 공급자가 2 를 구문 분석하고 기본 데이터 소스를 쿼리하는 데 더 적합한 형식으로 변환 할 수 있습니다. 예 :

//C#
IQueryable<Person> qry = PersonsSet();

// Since we're using a variable of type Expression<Func<Person,bool>>, the compiler 
// generates an expression tree representing this code
Expression<Func<Person,bool>> expr = x => x.LastName.StartsWith("A");
// The same thing happens when we write the lambda expression directly in the call to 
// Queryable.Where

qry = qry.Where(expr);


'VB.NET
Dim qry As IQueryable(Of Person) = PersonSet()

' Since we're using a variable of type Expression(Of Func(Of Person,Boolean)), the compiler 
' generates an expression tree representing this code
Dim expr As Expression(Of Func(Of Person, Boolean)) = Function(x) x.LastName.StartsWith("A")
' The same thing happens when we write the lambda expression directly in the call to 
' Queryable.Where

qry = qry.Where(expr)

예를 들어이 쿼리가 SQL 데이터베이스에 대해 수행되면 공급자는이 식을 다음 SQL 문으로 변환 할 수 있습니다.

SELECT *
FROM Persons
WHERE LastName LIKE N'A%'

데이터 소스에 대해 실행합니다.

반면에 쿼리가 REST API에 대해 수행되면 공급자는 동일한 표현식을 API 호출로 변환 할 수 있습니다.

http://www.example.com/person?filtervalue=A&filtertype=startswith&fieldname=lastname

표현식을 기반으로 데이터 요청을 조정할 때 두 가지 주요 이점이 있습니다 (전체 컬렉션을 메모리에로드하고 로컬로 쿼리하는 것과 반대).

  • 기본 데이터 원본은 종종보다 효율적으로 쿼리 할 수 ​​있습니다. 예를 들어 LastName 대한 색인이있을 수 있습니다. 로컬 메모리에 개체를로드하고 메모리를 쿼리하면 효율성이 떨어집니다.
  • 데이터는 전송되기 전에 형성 및 축소 될 수 있습니다. 이 경우 데이터베이스 / 웹 서비스는 데이터 소스에서 사용할 수있는 전체 Person 세트와 대조되는 일치하는 데이터 만 리턴하면됩니다.

노트
1. 기술적으로, 그들은 실제로 메소드를 사용하지 않고 메소드 를 가리키는 인스턴스를 위임합니다 . 그러나이 구별은 여기서는 부적합합니다.
2.이 이유이다 에러 "엔티티 LINQ 메소드를 인식하지 못하는 '선택 System.String ToString ()에있어서,이 방법은 저장 식으로 변환 될 수 없다.". LINQ 공급자 (이 경우 Entity Framework 공급자)는 ToString 에 대한 호출을 구문 분석하고 동등한 SQL로 변환하는 방법을 알지 못합니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow