본문 바로가기
IT/C#

LINQ(Lanuage-integrated Query) 쿼리식 DataTable 문법

by ^&**&^ 2022. 6. 28.
반응형


안녕하세요. 오늘은 LINQ에 대해 알아볼게요. 

LINQ(Language-integrated Query)란 프로그램 소스 상에서 Query처럼 쓸 수 있는 문법을 말합니다.

 
다시 말하면 애플리케이션 메모리 내에 있는 데이터 구조(객체 배열, list 등), XML 문서, SQL 데이터베이스 및 DataSet 개체와 같은 다양한 열거 가능한 데이터 원본에 소스 코드에서 데이터베이스 쿼리와 같은 문법으로 질의하여 데이터를 조회하는 기능인 거죠. 

자주 활용되는 부분이 데이터베이스에 질의해서 얻어온 DataTable에 Where나 Group by로 데이터를 추리거나 집계를 수행할 때 사용합니다. 

알아두면 편하긴 한데 쿼리를 질의하고자 하는 문법이 '쿼리식 구문'과 '메서드 기반 쿼리 구문' 두 개가 있기 때문에 배우는데 조금 귀찮기도 합니다. 


LINQ를 몰라도 반복문을 통해 데이터를 추리는 것이 가능하니 꼭 필수적으로 알고 있어야 하는 문법도 아니고요. 


하지만 다른 사람이 LINQ를 사용했다면 소스 코드를 이해하기 위해서라도 어쩔 수 없이 알아야 하는 문법이기도 하고요. 

 

 

Linq가 지원하는 데이터 형식

 

  1. INQ to DataSet
  2. LINQ to SQL
  3. LINQ to Entities


위 DataSet, SQL, Entities 세 데이터 형식은 IEnumeratble 또는 제네릭 IEnumeratble<T> 인터페이스를 지원하는 개체 컬렉션이죠. 


즉, IEnumeratble, IEnumeratble<T> 지원하는 개체는 LINQ를 사용할 수 있다는 말입니다.

그중에서 자주 사용하는 DataSet(DataTable) 데이터 형식의 '쿼리식 구분' LINQ 문법에 대해 알아보겠습니다. 

1
2
3
4
5
6
7
8
9
10
11
12
DataSet ds = new DataSet();
FillDataSet(ds);
 
DataTable products = ds.Tables["Product"];
 
IEnumeratble<DataRow> query = 
    from product in products.AsEnumerable()
    select product;
    
foreach(DataRow p in query){
    Console.WriteLine(p.Field<string>("Name"));
}
cs


기본적은 구문의 형식은 위와 같습니다. 

 

데이터 베이스 쿼리 문과 같이 from, select 구문을 사용해서 새로운 데이터 셋을 가져오는 것이죠. 


from 절에 데이터 소스를 지정하고 select, where, group by 등의 구문을 사용하여 데이터 셋에 필터 및 집계를 수행한 결과를 반환받습니다. 

 

 

from 구문 - 데이터 소스의 지정

 

from 절은 데이터 원본 및 내부에서 사용할 변수명을 지정합니다. 

1
2
from [변수명] in [데이터 소스]
from cust in Customers.AsEnumerable()
cs


위 구문을 해석하면 Customers DataTable을 LINQ 구문 안에서 'cust'라는 변수명으로 접근하겠다는 말입니다. 

1
2
3
4
5
6
int[] scores = { 97928160 }
 
IEnumeratble<int> query =
    from score in scores
    where score > 80
    select score;
cs


<T> 타입 값이 int형으로 기본 데이터 형식이면 score는 각 배열의 항목의 int값을 말하겠죠. 


<T> 타입 값이 DataRow형이라면 score는 각 DataTable의 Row가 되겠죠. 


같은 개념으로 select 뒤 score는 <T> 타입 값에 따라 결정됩니다. 

 

int로 선언하면 int값, DataRow는 DataRow가 되겠죠. 



 

쿼리식의 종료

 

쿼리식의 종료는 group 구문 또는 select 구문로 끝나야 합니다. 

 

 

Select 구문

 

소스 데이터에서 결과 데이터를 생성할 때는 select 구문을 사용합니다. 

 

1
2
3
var query =
    from row in SampleData.User().AsEnumerable()
    select row;
cs

[ DataTable의 전체 행컬럼을 반환 ]

 

1
2
3
4
5
6
7
var query =
    from row in SampleData.User().AsEnumerable()
    select new 
    {
        Name = row["UserName"],
        Age = row["Age"]
    };
cs

[ 일부 컬럼을 반환할 때 AnonymousType으로 반환 ]



위 소스 코드에서 var query처럼 변수 선언의 자료형을 var를 사용하는 것은 직접 타입을 지정하는 것보다 가독성이 좋습니다. 

1
2
3
IEnumerable<DataRow> query =
    from row in SampleData.User().AsEnumerable()
    select row;
cs

 

이렇게 직접 반환형의 객체 타입을 지정할 수도 있지만, select와 where절까지 포함된 LINQ의 결과는 System.Data.EnumerableRowCollection<System.Data.DataRow> 객체 형태로 반환하지만 group by 구문이 있으면 반환되는 형식이 System.Linq.Enumerable.SelectEnumeratbleIterator<System.Linq.IGrouping<<f_AnonymousType0<string, string>, System.Data.DataRow> 처럼 다른 객체로 반환합니다. 

 

또한 LINQ 구문 앞에도 명시적으로 형 변환 캐스트가 붙어야 해서 소스 코드의 가독성이 정말 떨어지게 됩니다.

 

그래서 var를 사용하는 것이 좋은 대안이 됩니다. 

 

 

where 구문

 

where구문은 쿼리의 where절 유사한 방식으로 작성합니다. 

 
1
2
3
4
var query =
    from row in SampleData.User().AsEnumerable()
    where row.Field<string>("PART_NO"== "P01"
    select row;
cs
 
 

group 구문

 

group 구문을 사용하면 System.Linq.GroupedEnumerable<System.Data.DataRow, string, System.Data.DataRow> 객체 타입으로 반환됩니다. 

1
2
3
var query =
    from row in dataTable.AsEnumerable()
    group row by row.Field<string>("EQPTID");
cs


query 객체는 "Grouping 된 항목명", 해당 grouping에 속하는 DataRow 집합 리스트로 반환됩니다. 

1
2
3
4
var query = 
    from row in dataTable.AsEnumerable()
    group row by row.Field<string>("EQPTID") into result
    select result;
cs

     
위 코드 System.Linq.Enumerable.WhereSelectEnumerableIterator<System.Linq.IGrouping<string, System.Data.DataRow> 객체를 반환합니다. 


result.Key와 reqult는 DataRow 형태로 그룹으로 묶이는 세부 데이터 Row가 들어가 있습니다. 

여러 컬럼을 그룹을 묶고 싶을 때는 아래처럼 사용합니다. 

1
2
3
4
5
6
7
8
9
var query = 
    from row in dataTable.AsEnumerable()
    group row by new { ID = row.Field<string>("EQPTID"), NAME = row.Field<string>("EQPT_MOUNT_NAME") } into result
    select new
    {
        EQPTID = result.Key.ID,
        EQPTNAME = result.Key.NAME
        // resulet 객체는 그룹으로 구성되는 DataRow가 들어옴 
    };
cs


LINQ의 실행 결과 객체의 query의 query.EQPTID, query.EQPTNAME 속성으로 가져온 데이터셋을 조회 가능합니다. 

 

반응형

'IT > C#' 카테고리의 다른 글

C# 생성자 및 소멸자  (0) 2022.06.14
객체 타입(Type) 비교 및 부모 클래스 타입 확인  (0) 2022.06.09

댓글