LINQ에서의 지역 질의와 해석식 질의
LINQ에서의 지역 질의와 해석식 질의
LINQ는 닷넷프레임워크에 포함, 다양한 기능에 적용되어 C#뿐 아니라 SQL Server, pwsh등 마이크로소프트의 다른 도구에서도 사용할 수 있다.
코드 관점에서, SQL Server처럼 코드 외부의 데이터 소스에 대해 작성하는 LINQ 질의를 해석식 질의 (Interpreted Query)라고할한다. 이와 대비해서 코드 내부의 컬렉션을 대상으로 작성하는 LINQ 질의는 지역 질의 (Local Query)이다.
지역 질의와 IEnumerable<T>
지역 질의는 데이터를 참조하기 위해 LINQ가 직접 코드 범위 바깥으로 나가지 않는다. 따라서 전적으로 IL 코드 범위 내에서 실행된다.
1
2
3
4
5
6
7
8
9
10
string[] languages = { "C", "C++", "Java", "C#", "Go", "Rust", "Python" }
IEnumerable<string> query =
from language in languages
select language.Replace("+", "p")
.Replace("#", "sharp")
into langNoSymbol
where langNoSymbol.Length > 2
orderby langNoSymbol
select langNoSymbol;
foreach (string lang in query) Console.WriteLine(lang);
1
2
3
4
5
Cpp
Csharp
Java
Python
Rust
C#의 모든 이터레이터는 IEnumerable<T>를 구현하므로 지역 질의는 IEnumerable<T>를 구현하는 모든 컬렉션들에 대해 작동한다.
해석식 질의와 IQueryable<T>
해석식 질의는 IQueryable<T>를 구현하는 순차열에 대해 작동한다. 해석식 질의는 IL 코드 범위에서 작동하는 지역 질의와 달리, Queryable 클래스의 질의 연산자를 통해 산출된 표현식 트리를 닷넷프레임워크 런타임이 코드를 실행하는 도중에 실행한다.
1
2
3
4
5
6
7
8
9
10
create table Account
(
ID int not null primary key,
loginName varchar(30),
displayName varchar(20)
)
insert Account values (1, 'ShapeLayer', '박종현')
insert Account values (2, 'dalcw', '문성수')
insert Account values (3, 'happyoung', '오다영')
insert Account values (4, 'Leopard', '성홍념')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using System;
using System.Linq;
using System.Data.Linq;
using System.Data.Linq.Mapping;
[Table] public class Account
{
[Column(IsPrimaryKey = true)] public int ID;
[Column] public string loginName;
[Column] public string displayName;
}
class Program
{
static void Main ()
{
DataContext dataContext = new DataContext("");
Table<Account> accounts = dataContext.GetTable<Account>();
IQueryable<string> query = from a in accounts
where a.loginName.ToUpper().Contains("L")
orderby a.loginName.Length
select a.displayName.SubString(1, 2);
foreach (string name in query) Console.WriteLine(name);
}
}
L2S는 쿼리를 SQL 쿼리로 변환하고 실행합니다.
1
2
3
4
SELECT [t0].[displayName] AS [value]
FROM [Account] AS [t0]
WHERE UPPER([t0].[loginName]) LIKE @P0
ORDER BY LEN([t0].[loginName])
1
2
3
문성수
성홍념
박종현
지역 질의와 해석식 질의의 혼용
하나의 쿼리 안에 지역 질의와 해석식 질의를 혼용해 사용할 수 있다.
일반적으로는 지역 연산자를 외부에, 해석식 연산자를 내부에 작성한다. 해석식 질의 결과를 지역 질의의 입력으로 사용하는 것이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
public static IEnumerable<string> Pair (this IEnumerable<string> source)
{
string prev = null;
foreach (string each in source)
{
if (prev == null) prev = each;
else
{
yield return $"{prev}, {each}";
prev = null
}
}
}
1
2
3
4
5
6
7
8
9
10
DataContext dataContext = new DataContext("");
Table<Account> accounts = dataContext.GetTable<Account>();
IEnumerable<string> query = accounts // 해석식 질의 시작: IQueryable<string>
.OrderBy (a => -(a.ID))
.Select (a => a.displayName)
.Pair() // 지역 질의 시작: IEnumerable<string>
.Select((n, i) => $"[{i}] {n}");
foreach (string row in query) Console.WriteLine(row);