2012년 5월 3일 목요일

516) LINQ 강좌

Taeyo.NET - ASP.NET 2.0




강좌 최초 작성일 : 2007년 10월 30일

강좌 최종 수정일 : 2007년 11월 12일







강좌 읽음 수 : 회



작성자 : kobukii(김 경균)

편집자 : Taeyo(김 태영)



강좌 제목 : LINQ란 무엇인가?





강좌 전 태오의 잡담>



이번 강좌는 태오 사이트의 멤버이자, Microsoft MVP인 김 경균님이 제공하는 LINQ에 관한 이야기입니다. 많은 분들이 관심을 가지고 있는 LINQ에 대해 기본적인 개념을 이해할 수 있는 강좌가 될 예정이니 많은 관심을 부탁드립니다.





--------------------------------------------------------------------------------



LINQ란 무엇인가?

LINQ는 Language Integrate Query의 약자로써 통합 질의 언어 라고 말할 수 있습니다..

기존의 Query는 Database의 데이터를 다루기 위해 사용하는 언어쯤으로 여겨 졌습니다. 하지만 LINQ는 컬렉션 형태로 되어있는 모든 데이터에 대해 질의를 할 수 있는 마이크로소프트의 새로운 기술입니다.

예를 들자면 MS-SQL의 데이터를 가져오는데 LINQ를 사용할 수 있는 것은 물론이고 메모리상의 컬렉션 또는 XML에 대해서도 LINQ를 사용할 수 있습니다.

지금부터 이 강력한 통합질의언어인 LINQ에 대해 알아보도록 하겠습니다.



1. Extension Method(확장 메서드)



Extension Method(이하 확장메서드)는 기존의 타입에 매서드를 추가하거나 재컴파일 할 필요 없이 이미 존재하는 CLR타입에 새로운 메서드를 추가할 수 있게 설계된 메서드 입니다.



//static클래스를 생성해야 한다.

public static class KClass

{

//static메서드로 생성해야 한다.

public static int isOdd(this int n)

{

//홀수일 경우 1을 반환한다.

if (n % 2 == 1)

return n;

return 0;

}

}



int num = 5;

//int형의 변수 뒤에 isOdd()를 사용할 수 있다.

//num이 5이므로 5를 반환한다.

int oddValue = num.isOdd();





LINQ 와 확장메서는 무슨 관계인가? 확장메서드는 LINQ에서 쿼리를 위한 메서드(Select, Where...)는 확장 메서드로 되어 있기 때문입니다.







위의 캡쳐화면을 보면 분홍색 육면체는 일반 메서드를 나타냅니다. 그 중에서 파란색의 아래방향 화살표가 있는 것이 확장메서드를 나타내는 아이콘인데 위에서는 All, Any, Average등이 있습니다.



LINQ에서는 상당히 많은 수의 확장메서드를 사용합니다. 거의 모든 메서드가 확장메서드라고 봐도 무방할 정도죠. 확장메서드는 LINQ뿐만이 아니라 일반 코드에서도 응용할 수 있기에 이장에서 다루어 보았습니다.



2. Anonymous Type(익명 타입)



Anonymous Type은 타입의 선언을 명확하게 정의하지 않고 코드 내의 CLR타입을 간단하게 정의하는 것이 가능한 C#3.0의 편리한 기능입니다.



public class Tech

{

public string Upper{ get; set;}

public string Lower{ get; set;}

}



string[] strs = {"ASp.NeT","AjAx","SilvErLigHt"};

IEnumerable techs = from s in strs

select new Tech

{

Upper = s.ToUpper(),

Lower = s.ToLower()

};

foreach (Tech t in techs)

{

Response.Write(t.Lower + "," + t.Upper + "");

}

위의 예제는 Query Syntax를 사용합니다. 아직 Query Syntax의 사용법에 대하여 배우지는 않았지만 Anonymous Type에 대햐여 알아보기 위해 간단한 Query Syntax를 사용하였습니다.

우선 Upper와 Lower프로퍼티를 갖는 Tech라는 클래스를 만들었습니다.(이 클래스는 프로퍼티 생성방법이 기존과 약간 다릅니다. 이를 Automatic Propertity라고 합니다.)

strs라는 문자열 배열에는 대소문자가 구분되지 않은 세 개의 문자열이 있습니다. from절에서 strs를 사용하겠다고 명시했고 select절에서는 new Tech키워드를 이용해 앞에서 만들었던 Tech타입으로 개체를 생성합니다. 그리고 각각 Upper와 Lower에 값을 할당합니다.

이를 받는 techs변수는 Tech를 타입매개변수로 하는 IEnumeable형으로 선언합니다.



Query Syntax를 이용하여 미리 정의된 타입으로 데이터를 쿼리 했습니다. 상당히 명시 적이지만 Tech타입이 범용적으로 쓰이지 않고 현재 코드 부분에서 한시적으로 사용된다면 코드가 많이 복잡해 질 수 있습니다.

이를 좀더 간단하게 사용하기 위해 나온 것이 Anonymous Type입니다.



string[] strs = {"ASp.NeT","AjAx","SilvErLigHt"};

var texts = from s in strs

select new

{

upper = s.ToUpper(),

lower = s.ToLower()

};

foreach(var t in texts)

{

Response.Write(t.lower + "," + t.upper + "");

}



위의 코드는 앞의 코드에 비해 상당히 간단해 졌습니다. 일단 Tech클래스 정의가 없어졌습니다. select절을 보면 new키워드 다음 Tech클래스 생성자가 없어진 것을 볼 수 있습니다.

클래스의 생성자 없이 바로 new키워드를 통해 개체를 생성하고 임의로 upper와 lower를 만들어 값을 할당합니다.

이것이 바로 Anonymous Type입니다. 익명으로 타입을 생성한 것입니다.

그래서 이 쿼리 결과는 타입이 명확하지 않기 때문에 IEnumeable<>형으로 받지 않고 var 키워드를 사용하게 됩니다.



다음은 var 키워드에 대해 알아보도록 하겠습니다.



3. var 키워드



c#3.0에서 가장 충격적인 부분이라고 생각하는 var키워드에 대해 알아보겠습니다.

var 키워드는 기존의 인터프리터언어(javascript..)에서 사용되는 형식이 정해지지 않은 어떠한 임의의 변수를 나타냅니다.

C#에서도 드디어 var키워드가 도입 되었는데 기존의 인터프리터언어에서의 var와는 개념이 약간 다릅니다.

기존의 var타입은 프로그램을 실행하는 동안 즉, 런타임 시 타입이 결정되는 반면 C#의 var타입은 컴파일 시에 타입이 결정됩니다.



이제 var키워드로 모든 변수를 대체할 수 있습니다. 타입에 더 이상 신경 쓰지 않고 개발이 가능합니다.

하지만 ASP.NET에서는 사용자가 페이지를 볼 때까지 걸리는 시간에 컴파일 타임이 포함 됩니다. var키워드를 남발하면 컴파일 타임이 늘어나게되어 사용자가 화면을 볼 때까지 걸리는 시간이 길어지므로 짜증날 수도 있기 때문에 var타입은 적절히 필요한 LINQ관련 부분에서 사용하거나 반드시 필요한 부분에서 사용하는 것이 현명한 선택 일 것입니다.



var 타입에 대해 알아 두셔야 할 중요한 체크 포인트가 있습니다.



var 타입은 모든 데이터 타입이 될 수 있습니다. 하지만 초기값을 할당하지 않을 경우 컴파일 타임에 어떠한 타입인지 알 수 없기 때문에 선언과 동시에 값을 할당 해야 합니다.

이 부분이 기존 인터프리터 언어와 다른 가장 중요한 차이점입니다. 비쥬얼스튜디오로 작업할 때 var 타입 변수에 밑줄이 나타나면 초기 값을 할당 했는지 우선 확인해 보세요.



Anonymous Type의 두 번째 예제를 다시 살펴보면 쿼리 한 결과값을 var타입으로 받은 것을 확인 할 수 있습니다.

이는 select절에서 데이터를 가져올 때 new키워드 만을 사용했고 어떠한 타입인지 알 수 없는 Anonymous Type이기 때문에 var키워드를 사용하여 값을 할당 받게 됩니다.

컴파일 타임에 var 타입은 select한 타입을 확인한 다음 특정 타입으로 치환해 주게 되는 것입니다.

그 다음 아래 코드의 foreach문에서도 타입을 정확히 알 수 없기 때문에 var키워드를 사용할 것을 확인할 수 있습니다.



4. Lambda Expression(람다 표현식)



용어사전의 설명에 의하면 Lambda Expression은 '어떤 문제를 해결하기 위한 과정을 수학적 함수를 이용하여 표현한 수식'이라고 설명되어 있습니다.

C#3.0의 Lambda Expression의 기능과 일맥상통하는 부분입니다.



Lambda Expression은 C#2.0에서 도입되었던 Anonymous Delegate(익명 대리자, 무명 메서드)를 좀 더 실용적으로 만든 것으로써 Lambda Expression은 컴파일 과정에서 Delegate(대리자)로 치환됩니다. 간단히 설명하면 Lambda Expression은 컬렉션에 질의를 하기 위해 LINQ에서 사용되는 표현식이라고 알아두시면 될 것 같습니다.



(매개변수들)=>(표현식)



Lambda Expression은 위와 같이 나타낼 수 있습니다. 간단한 Lambda Expression의 예를 살펴보도록 하겠습니다.



int[] numbers = {1,2,3,4,5,6,7,8,9};

1. IEnumerable odds = numbers.Where(n=>n%2==1);

2. IEnumerable odds = numbers.Where((int n)=>n%2==1);

3. IEnumerable odds = numbers.Where(delegate(int n){return n%2==1;});



Where메서드는 C#3.0에서 추가된 IEnumerable의 값에 순차적으로 접근하여 그 값을 필터링 하기 위한 확장메서드 입니다. 확장메서드에 대한 자세한 설명은 뒤에서 하도록 하겠습니다.



Where의 파라미터를 보면 (매개변수들)=>(표현식)과 같은 형태로 되어 있습니다. numbers의 값들을 차례로 이동하며 홀수인 경우 값을 반환하게 됩니다.

1번의 표현식을 좀더 명확하게 나타내면 2번과 같이 n을 int n으로 나타낼 수 도 있습니다.

3번의 경우에는 1번 또는 2번의 표현식이 컴파일 될 때 만들어지는 코드로 Anonymous Delegate형태로 생성되게 됩니다. 처음부터 3번과 같은 방식으로 사용해도 상관 없지만 간결함을 위해 1번과 같은 Lambda Expression을 사용 하는 것을 권장 합니다.



5. Query Syntax

Query Syntax란 표준 LINQ query 연산자를 사용하여 쿼리를 표현하기 위한 선언적 표기 방법입니다.

Query Syntax는 기존의 쿼리처럼 문자열을 이용하는 방식이 아니라 코드상에 기존 코드를 입력하듯이 깔끔하게 쿼리를 작성할 수 있습니다. 또한 정확하게 읽고 쓰는 것이 가능하며 쉽게 그 내용을 확인 할 수 있습니다.

또 하나의 편리한 점은 Visual Studio를 사용 할 경우 완벽한 인텔리센스를 제공하며 컴파일 타임의 체크 또한 지원합니다.

Qyery Syntax 표현은 의미상으로 LINQ 확장메서드와 Lambda Expression을 사용하는 것과 동일합니다.

하지만 사용법 자체가 기존의 Query와 동일하여 개발자는 이에 좀더 쉽게 다가갈 수 있을 것 같습니다.



int[] numbers = {1,2,3,4,5,6,7,8,9};

int[] selNums = from n in numbers

where n>5;

select n;

위의 Query Syntax는 numbers배열에서 5보다 큰 숫자들을 가져오는 표현식입니다.

기존의 Query와 다른 점이 있다면 각 절의 위치가 기존과는 다르게 form절이 가장 상위에 오고 그 다음 where절 마지막으로 select절이 오는 것을 확인 할 수 있습니다.

처음 Query Syntax를 사용할 경우 적응하기 어려울 수 있지만 자세히 보면 기존의 Query보다 더 명확하게 사용 할 수 있다는 것을 알 수 있습니다.

가장 먼저 어디서 데이터를 가져올 것인지를 정하고(from), 가져온 데이터 중에서 어떤 데이터를 걸러낼 것이며(where), 걸러진 데이터를 어떤 형태로 가져올 것인가(select)를 정의하게 됩니다.



Query Syntax에서 from절은 foreach와 상당히 유사하다는 것을 알 수 있습니다.

n이라고 가정한 변수와 이 변수의 제한 범위를 설정하는 나열될 수 있는 개체 numbers를 지정한 것이 foreach와 상당히 유사하며 이어지는 절(where, select)에서 가정한 변수 n을 사용하는것 또한 상당히 유사합니다.



이어지는 where절과 select절 등은 다음 강좌에서 중점 적으로 설명하도록 하겠습니다.



이번 아티클에서는 LINQ를 사용하기 위해 그 기반이 되는 Lambda Expression, Extension Method, Anonymous Type, var 키워드, Query Syntax 에 대해 알아 보았습니다.

다음 강좌에서는 메모리 상의 컬렉션 개체에 LINQ를 적용하는 방법과 Lamba Expression을 보다 유연하게 사용할 수 있도록 많은 예제를 통해 LINQ에 한걸음 더 깊숙이 들어가 보도록 하겠습니다.

다음 강좌를 기대해 주세요..^^ 감사합니다.









Taeyo.NET - ASP.NET 2.0




강좌 최초 작성일 : 2007년 12월 17일

강좌 최종 수정일 : 2008년 01월 01일



강좌 읽음 수 : 회



작성자 : kobukii(김 경균)

편집자 : Taeyo(김 태영)



강좌 제목 : LINQ to SQL





강좌 전 태오의 잡담>



이번 강좌는 태오 사이트의 멤버이자, Microsoft MVP인 김 경균님이 제공하는 LINQ에 관한 이야기입니다. 많은 분들이 관심을 가지고 있는 LINQ에 대해 기본적인 개념을 이해할 수 있는 강좌가 될 예정이니 많은 관심을 부탁드립니다.





--------------------------------------------------------------------------------



LINQ to SQL에 대하여 알아보자

이번 강좌에서는 LINQ to SQL을 사용하는 방법을 간단한 Blog 예제를 통해 알아보도록 하겠습니다. LINQ to SQL은 LINQ의 한 부분으로 SQL서버의 데이터를 좀 더 편리하고 직관적으로 다룰 수 있게 해주는 Microsoft의 새로운 기술입니다. 최신 버전의 LINQ는 .NET Framework3.5가 정식 릴리즈 되면서 약간 변경된 부분이 있으며 본 강좌에서는 새롭게 릴리즈된 .NET Framework3.5 기반으로 코드를 작성하였습니다.

또한 이 글의 모든 코드는 Visual Studio 2008 RTM버전으로 작성 되었습니다.



1. 웹프로젝트 생성 및 dbml(LINQ to SQL Classes)생성



가장 먼저 Web Project를 생성합니다.







웹 어플리케이션을 생성한 후 프로젝트 및 솔루션 이름을 Lec_Blog로 입력 합니다.



다음으로 LINQ to SQL Classes템플릿을 선택하여 Blog.dbml이라는 이름으로 파일을 생성합니다.







LINQ to SQL Classes를 생성하면 LINQ to SQL Designer화면이 나타나게 되며 이 영역에 데이터베이스를 표현하는 모델 클래스를 추가할 수 있습니다. 테이블, 저장프로시저, 사용자 정의 함수 등이 추가되면 LINQ to SQL Classes는 실제 데이터베이스의 각 테이블을 나타내는 프로퍼티와 저장 프로시저를 나타내는 매서드 등을 포함하는 DataContext클래스를 생성하게 됩니다. DataContext클래스는 변경된 데이터를 적용하거나 데이터베이스로부터 데이터를 쿼리 할 때 반드시 사 용하게 되는 LINQ to SQL의 핵심이 되는 클래스 입니다.



LINQ to SQL Classes 파일을 추가하면 다음과 같은 LINQ to SQL Designer 화면이 나타나게 됩니다.







LINQ to SQL Designer의 왼쪽 영역에 테이블을 끌어 놓게 되면 데이터 클래스를 자동으로 생성합니다. 오른쪽 영역은 저장프로시저 또는 사용자정의 함수를 끌어 놓을 경우 각 저장프로시저와 사용자 정의 함수에 해당되는 매서드를 자동으로 생성합니다.



LINQ to SQL Designer의 왼쪽 영역에 테이블을 추가 해 보도록 하겠습니다.



우선 Server Explorer을 열고 데이터베이스에 연결합니다.







미리 추가한 Lec_Blog 데이터베이스를 선택하고 ok버튼을 클릭합니다.

데이터베이스가 추가 되면 아래 이미지와 같은 형태로 Server Explorer가 구성됩니다.







Server Explorer에서 Category테이블과 Post테이블을 LINQ to SQL Designer의 왼쪽 영역 끌어 놓으면 끌어 놓은 각 테이블들이 시각적으로 표시 됩니다.







이제 LINQ to SQL을 이용하여 간단한 블로그 개발을 하기 위한 기본적인 준비가 완료 되었습니다.

테이블 스키마 및 소스코드는 여기서 다운로드 받으실 수 있습니다.



다운로드 받으시려면 클릭하세요



2. 데이터 가져오기(SELECT)



Post.aspx라는 웹페이지를 추가합니다. 이 페이지는 포스트를 작성, 수정 그리고 삭제 하는 기능을 갖고 있는 페이지 입니다. 페이지의 구성은 카테고리를 선택할 수 있는 DropDownLIst, 제목과 텍스트를 입력 받는 TextBox 그리고 저장을 위한 Button으로 구성되어 있습니다.



첫번째로 새 포스트를 작성할 때 카테고리를 선택할 수 있는 기능을 추가 하도록 하겠습니다.



BlogDataContext db;

protected void Page_Load(object sender, EventArgs e)

{

db = new BlogDataContext();

if (!IsPostBack)

{

cateogryBind();

}

}

private void cateogryBind()

{

IQueryable category = from c in db.Categories

select c;

//IQueryable category = db.Categories.Select(p => p);

ddlCategory.DataSource = category;

ddlCategory.DataBind();

}

위의 코드에서 가장 먼저 알아야 할 부분이 BlogDataContext입니다. 앞에서도 말한 것 처럼 DataContext클래스는 변경된 데이터를 적용하거나 데이터베이스로부터 데이터를 쿼리 할 때 반드시 사용하게 되는 LINQ to SQL의 핵심이 되는 클래스 입니다.



코드의 categoryBind 매서드를 보면 쿼리구문을 이용하여 Category테이블의 모든 데이터를 가져와 IQueryable타입의 변수에 할당 합니다.

쿼리구문을 보면 from절에서 데이터를 가져오게 될 데이터소스를 지정합니다. BlogDataContext의 인스턴스인 db개체를 이용하여 Categories에 접근하며 이 Categories(Category테이블 클래스)의 entity를 c라 가정하고 특별한 조건(Where절) 없이 c를 Select합니다. 이는 카테고리 테이블의 모든 데이터를 가져온다는 의미와 같습니다.

쿼리구문 아래 주석으로 처리된 부분은 쿼리구문을 사용하는 대신 Lambda Expression을 사용하여 데이터를 가져오는 또 다른 방법입니다. 어떤 방법을 사용해도 결과는 동일합니다.



가져온 데이터를 DropDownList의 DataSource에 할당하고 바인드를 합니다.

DropDownList의 DataSource로 ListItemCollection타입을 사용하지 않을 경우에는 DataTextField와 DataValueField를 반드시 지정해야 합니다. 이를 각각 CategoryName과 CategoryID로 지정 해 주면 Category를 선택할 수 있는 DropDownList가 만들어 지게 됩니다.



데이터의 조회는 마지막 챕터에서 더 자세히 알아보도록 하겠습니다.



3. 데이터 저장(INSERT)



다음으로 포스트의 내용을 저장하는 방법에 대해 알아보겠습니다.



protected void btnSubmit_Click(object sender, EventArgs e)

{

Post post = new Post();

post.Title = txtTitle.Text;

post.Content = txtContent.Text;

post.PubDate = DateTime.Now;

post.CategoryID = Convert.ToInt32(ddlCategory.SelectedItem.Value);

db.Posts.InsertOnSubmit(post);

}

LINQ to SQL Classes에 Category와 Post테이블을 끌어 놓았기 때문에 각 테이블의 entity에 해당하는 Post 및 Category클래스가 생성 됩니다.

가장먼저 Post의 인스턴스를 만듭니다. LINQ는 테이블의 필드명을 쉽게 확인 할 수 있도록 완벽한 인텔리센스를 제공합니다. 생성된 post개체의 각 필드에 값을 할당합니다. 마지막으로 테이블에 해당하는 db.Posts의 InsertOnSubmit을 호출합니다. Posts의 InsertOnSubmit매서드는 매개변수로 Posts의 entity인 Post타입의 개체를 받습니다.



여기서 기존에 LINQ를 사용 해 보신 분들께서는 InsertOnSubmit매서드가 생소할 수 있습니다. 기존에는 분명 Add매서드를 이용하여 데이터를 추가하고 OnSubmitChange매서드를 호출하여 데이터를 전송했었지만 정식버전의 출시와 함께 약간의 매서드가 변경 되었습니다.



Beta1 and Beta2 VS 2008 RTM

Add() InsertOnSubmit()

AddAll() InsertAllOnSubmit()

Remove() DeleteOnSubmit()

RemoveAll() DeleteAllOnSubmit()



위의 표는 Beta에서 RTM로 버전 업 되면서 변경된 매서드 들입니다. 참고 하세요..



4. 데이터의 수정 및 삭제



데이터를 수정하거나 삭제하기 위해서는 가장 먼저 수정이나 삭제를 하기 위한 데이터를 가져와 entity 개체를 생성해야 합니다.



Post post;

int postId = Convert.ToInt32(Request.QueryString["postid"]);

if (postId > 0)

{

post = db.Posts.Single(p => p.PostID == postId);

}

데이터의 삽입과 마찬가지로 entity개체의 각 속성에 값을 할당합니다.



post.Title = txtTitle.Text;

post.Content = txtContent.Text;

post.PubDate = DateTime.Now;

post.CategoryID = Convert.ToInt32(ddlCategory.SelectedItem.Value);

값을 모두 할당 한 다음 변경된 값을 처리하기 위해 BlogDataContext의 SubmitChanges 매서드를 호출하여 수정을 완료 합니다.



db.SubmitChanges();

데이터 삭제의 경우는 entity개체를 생성한 후 db개체의 DeleteOnSubmit매서드를 호출 하기만 하면 삭제 처리가 이루어 집니다.



5. 쿼리구문의 용법 및 컨트롤 데이터 바인딩



지금부터 조금 더 다양한 LINQ 쿼리 구문을 이용하여 데이터를 가져오고 또한 가져온 데이터를 ListView컨트롤에 바인딩 하는 방법을 블로그의 매인 페이지를 만들면서 보다 자세히 설명하도록 하겠습니다.





블로그의 메인페이지는 왼쪽 카테고리 영역과 오른쪽 포스트목록 영역으로 나누도록 하겠습니다.

이 두 부분은 .Net Frameowrk3.5에서 새롭게 등장한 ListView컨트롤을 사용하고 있습니다.



















  • ">






  • ListView컨트롤의 사용법은 본 강좌의 주제에서 벗어나기 때문에 간단하게 설명 하도록 하겠습니다.

    ListView컨트롤은 간단히 LayoutTemplete과 ItemTemplete영역으로 나눌 수 있는데 LayoutTemplete은 목록의 헤더 또는 목록을 감싸는 Tag를 지정하여 기본 Layout을 지정하는 영역입니다. 반복되는 데이터를 표현하는 부분을 PlaceHolder를 통해 지정해주고 이 컨트롤의 아이디를 ListView컨트롤의ItemPlaceholderID속성에 지정합니다.

    ItemTemplete영역은 실제 반복되는 부분을 만들어 줍니다. 데이터는 Eval매서드를 통해 지정해 줍니다. 이곳에서 반복적으로 생성된 코드가 LayoutTemplete의 PlaceHolder컨트롤에 표현됩니다.



    다음으로 데이터를 ListView컨트롤에 바인딩 하는 코드는 아래와 같습니다.



    List categories = db.Categories.ToList();

    categoryList.DataSource = categories;

    categoryList.DataBind();

    코드는 DropDownList에 데이터를 바인딩 했을 때와 상당히 유사합니다. 다른 점은 ToList() 확장 매서드를 사용하여 반환 타입을 List타입으로 한다는 것입니다.





    쿼리구문은 기본적으로 IQueryable형태로 만들어 지게 됩니다. 이 타입은 루프를 돌면서 값을 사용하기 시작할 때 실제 DB와 통신을 하여 값을 가져오게 됩니다.

    위의 이미지에서도 확인 되듯이 디버그를 해 보면 var categories 부분 에서는 아무런 데이터를 받아 오지 못하고 DataSource에 값을 할당 하였을 때 비로소 데이터를 받아 온 것을 볼 수 있습니다.





    위의 코드는 ToList() 확장 매서드를 사용한 경우인데 이때는 categories변수에 마우스를 올리자 바로 값을 받아 온 것을 확인 할 수 있습니다.

    ToList(), ToArray()와 같은 확장 매서드를 사용하면 데이터의 타입을 변경하는 동시에 즉시 데이터베이스와 통신을 하여 값을 받아 올 수 있습니다.



    마지막으로 Where구문을 사용하여 조건 별로 데이터를 가져오고 Skip과 Take확장 매서드를 사용하여 페이징을 처리 하는 부분에 대해 알아보도록 하겠습니다.





    1) 조건 절을 이용한 데이터 조회 및 정렬(단일 포스트 가져오기)



    List posts = (from p in db.Posts

    where p.PostID == postid

    orderby p.PubDate descending //정렬

    select p).ToList();

    위의 코드에서는 where절을 사용하여 PostID값을 비교하여 데이터를 가져오며 orderby절을 이용하여 PubDate를 기준으로 내림차순으로 정렬합니다.



    2) 페이징(한 화면에 보여 줄 포스트들을 가져오기)



    List posts = (from p in db.Posts

    orderby p.PubDate descending

    select p).Skip(currentPageIdx * itemCount).Take(itemCount).ToList();

    PubDate를 기준으로 정렬 하며 Skip확장 매서드를 통해 [현재페이지번호*한 페이지의 항목 수]만큼을 skip하고 Take확장 매서드를 사용하여 한 페이지의 항목 수 만큼 가져옵니다.



    3) 조건 절과 페이지을 모두 이용한 데이터 조회(카테고리 별 목록을 페이징을 통하여 가져오기)



    List posts = (from p in db.Posts

    where p.CategoryID == categoryid

    orderby p.PubDate descending

    select p).Skip(currentPageIdx * itemCount).Take(itemCount).ToList();

    위에서 가져온 데이터를 ListView컨트롤에 바인딩 하기 위해 ListView컨트롤을 구성하면



    // Category영역































  • // 포스트 영역


















    블로그 포스트 영역에서는 LayoutTemplate에 PlaceHolder컨트롤을 추가하고 ItemTemplete에 제목영역과 설명영역(발행일, 카테고리, 수정버튼), 컨텐츠 영역을 각 div태그로 생성합니다.

    데이터는 Eval매서드를 통하여 지정을 하는데 여기서 특이한 점은 부분에서 CategoryName을 가져오는 것입니다. Post테이블에는 CategoryID만 존재할 뿐 CategoryName은 존재하지 않는데 위의 코드에서는 CategoryName을 지정해 줬다는 것입니다. 이는 Post테이블이 CategoryID속성을 통해 Category테이블과 연관관계를 맺고 있으므로 Post의 Category개체를 통해 CategoryName에 접근 할 수 있게 되는 것 입니다.



    카테고리 영역에서는 Unorder List(UL)태그를 ListView컨트롤에 사용하여 카테고리 역영을 생성합니다. LayoutTemplete영역을
      태그로 구성하고 반복데이터가 표현될 영역을 PlaceHolder컨트롤로 지정합니다. ItemTelplete영역은
    • 태그를 사용하여 반복되는 데이터를 표현합니다.

      ListView컨트롤은 반드시 테이블 형태가 아닌 어떠한 반복 구조도 표현 할 수 있는 장점이 있습니다.



      이번 글에서는 LINQ to SQL의 간단한 사용법에 대해서 알아 보았습니다. '어떻게 LINQ to SQL을 사용할 수 있는 가'에 초점을 맞추었기 때문에 LINQ의 일반적인 사용법에 대해서만 알아 보았습니다. 다음 강좌는 다양한 쿼리구문과 Lambda Expression 예제를 통해 LINQ에 대해 보다 자세히 알아보도록 하겠습니다.



      그럼 다음강좌에서 다시 뵙도록 하겠습니다.^^ 감사합니다.



      Taeyo.NET - ASP.NET 2.0




      강좌 최초 작성일 : 2007년 12월 17일

      강좌 최종 수정일 : 2008년 01월 01일



      강좌 읽음 수 : 회



      작성자 : kobukii(김 경균)

      편집자 : Taeyo(김 태영)



      강좌 제목 : LINQ to SQL





      강좌 전 태오의 잡담>



      이번 강좌는 태오 사이트의 멤버이자, Microsoft MVP인 김 경균님이 제공하는 LINQ에 관한 이야기입니다. 많은 분들이 관심을 가지고 있는 LINQ에 대해 기본적인 개념을 이해할 수 있는 강좌가 될 예정이니 많은 관심을 부탁드립니다.





      --------------------------------------------------------------------------------



      LINQ to SQL에 대하여 알아보자

      이번 강좌에서는 LINQ to SQL을 사용하는 방법을 간단한 Blog 예제를 통해 알아보도록 하겠습니다. LINQ to SQL은 LINQ의 한 부분으로 SQL서버의 데이터를 좀 더 편리하고 직관적으로 다룰 수 있게 해주는 Microsoft의 새로운 기술입니다. 최신 버전의 LINQ는 .NET Framework3.5가 정식 릴리즈 되면서 약간 변경된 부분이 있으며 본 강좌에서는 새롭게 릴리즈된 .NET Framework3.5 기반으로 코드를 작성하였습니다.

      또한 이 글의 모든 코드는 Visual Studio 2008 RTM버전으로 작성 되었습니다.



      1. 웹프로젝트 생성 및 dbml(LINQ to SQL Classes)생성



      가장 먼저 Web Project를 생성합니다.







      웹 어플리케이션을 생성한 후 프로젝트 및 솔루션 이름을 Lec_Blog로 입력 합니다.



      다음으로 LINQ to SQL Classes템플릿을 선택하여 Blog.dbml이라는 이름으로 파일을 생성합니다.







      LINQ to SQL Classes를 생성하면 LINQ to SQL Designer화면이 나타나게 되며 이 영역에 데이터베이스를 표현하는 모델 클래스를 추가할 수 있습니다. 테이블, 저장프로시저, 사용자 정의 함수 등이 추가되면 LINQ to SQL Classes는 실제 데이터베이스의 각 테이블을 나타내는 프로퍼티와 저장 프로시저를 나타내는 매서드 등을 포함하는 DataContext클래스를 생성하게 됩니다. DataContext클래스는 변경된 데이터를 적용하거나 데이터베이스로부터 데이터를 쿼리 할 때 반드시 사 용하게 되는 LINQ to SQL의 핵심이 되는 클래스 입니다.



      LINQ to SQL Classes 파일을 추가하면 다음과 같은 LINQ to SQL Designer 화면이 나타나게 됩니다.







      LINQ to SQL Designer의 왼쪽 영역에 테이블을 끌어 놓게 되면 데이터 클래스를 자동으로 생성합니다. 오른쪽 영역은 저장프로시저 또는 사용자정의 함수를 끌어 놓을 경우 각 저장프로시저와 사용자 정의 함수에 해당되는 매서드를 자동으로 생성합니다.



      LINQ to SQL Designer의 왼쪽 영역에 테이블을 추가 해 보도록 하겠습니다.



      우선 Server Explorer을 열고 데이터베이스에 연결합니다.







      미리 추가한 Lec_Blog 데이터베이스를 선택하고 ok버튼을 클릭합니다.

      데이터베이스가 추가 되면 아래 이미지와 같은 형태로 Server Explorer가 구성됩니다.







      Server Explorer에서 Category테이블과 Post테이블을 LINQ to SQL Designer의 왼쪽 영역 끌어 놓으면 끌어 놓은 각 테이블들이 시각적으로 표시 됩니다.







      이제 LINQ to SQL을 이용하여 간단한 블로그 개발을 하기 위한 기본적인 준비가 완료 되었습니다.

      테이블 스키마 및 소스코드는 여기서 다운로드 받으실 수 있습니다.



      다운로드 받으시려면 클릭하세요



      2. 데이터 가져오기(SELECT)



      Post.aspx라는 웹페이지를 추가합니다. 이 페이지는 포스트를 작성, 수정 그리고 삭제 하는 기능을 갖고 있는 페이지 입니다. 페이지의 구성은 카테고리를 선택할 수 있는 DropDownLIst, 제목과 텍스트를 입력 받는 TextBox 그리고 저장을 위한 Button으로 구성되어 있습니다.



      첫번째로 새 포스트를 작성할 때 카테고리를 선택할 수 있는 기능을 추가 하도록 하겠습니다.



      BlogDataContext db;

      protected void Page_Load(object sender, EventArgs e)

      {

      db = new BlogDataContext();

      if (!IsPostBack)

      {

      cateogryBind();

      }

      }

      private void cateogryBind()

      {

      IQueryable category = from c in db.Categories

      select c;

      //IQueryable category = db.Categories.Select(p => p);

      ddlCategory.DataSource = category;

      ddlCategory.DataBind();

      }

      위의 코드에서 가장 먼저 알아야 할 부분이 BlogDataContext입니다. 앞에서도 말한 것 처럼 DataContext클래스는 변경된 데이터를 적용하거나 데이터베이스로부터 데이터를 쿼리 할 때 반드시 사용하게 되는 LINQ to SQL의 핵심이 되는 클래스 입니다.



      코드의 categoryBind 매서드를 보면 쿼리구문을 이용하여 Category테이블의 모든 데이터를 가져와 IQueryable타입의 변수에 할당 합니다.

      쿼리구문을 보면 from절에서 데이터를 가져오게 될 데이터소스를 지정합니다. BlogDataContext의 인스턴스인 db개체를 이용하여 Categories에 접근하며 이 Categories(Category테이블 클래스)의 entity를 c라 가정하고 특별한 조건(Where절) 없이 c를 Select합니다. 이는 카테고리 테이블의 모든 데이터를 가져온다는 의미와 같습니다.

      쿼리구문 아래 주석으로 처리된 부분은 쿼리구문을 사용하는 대신 Lambda Expression을 사용하여 데이터를 가져오는 또 다른 방법입니다. 어떤 방법을 사용해도 결과는 동일합니다.



      가져온 데이터를 DropDownList의 DataSource에 할당하고 바인드를 합니다.

      DropDownList의 DataSource로 ListItemCollection타입을 사용하지 않을 경우에는 DataTextField와 DataValueField를 반드시 지정해야 합니다. 이를 각각 CategoryName과 CategoryID로 지정 해 주면 Category를 선택할 수 있는 DropDownList가 만들어 지게 됩니다.



      데이터의 조회는 마지막 챕터에서 더 자세히 알아보도록 하겠습니다.



      3. 데이터 저장(INSERT)



      다음으로 포스트의 내용을 저장하는 방법에 대해 알아보겠습니다.



      protected void btnSubmit_Click(object sender, EventArgs e)

      {

      Post post = new Post();

      post.Title = txtTitle.Text;

      post.Content = txtContent.Text;

      post.PubDate = DateTime.Now;

      post.CategoryID = Convert.ToInt32(ddlCategory.SelectedItem.Value);

      db.Posts.InsertOnSubmit(post);

      }

      LINQ to SQL Classes에 Category와 Post테이블을 끌어 놓았기 때문에 각 테이블의 entity에 해당하는 Post 및 Category클래스가 생성 됩니다.

      가장먼저 Post의 인스턴스를 만듭니다. LINQ는 테이블의 필드명을 쉽게 확인 할 수 있도록 완벽한 인텔리센스를 제공합니다. 생성된 post개체의 각 필드에 값을 할당합니다. 마지막으로 테이블에 해당하는 db.Posts의 InsertOnSubmit을 호출합니다. Posts의 InsertOnSubmit매서드는 매개변수로 Posts의 entity인 Post타입의 개체를 받습니다.



      여기서 기존에 LINQ를 사용 해 보신 분들께서는 InsertOnSubmit매서드가 생소할 수 있습니다. 기존에는 분명 Add매서드를 이용하여 데이터를 추가하고 OnSubmitChange매서드를 호출하여 데이터를 전송했었지만 정식버전의 출시와 함께 약간의 매서드가 변경 되었습니다.



      Beta1 and Beta2 VS 2008 RTM

      Add() InsertOnSubmit()

      AddAll() InsertAllOnSubmit()

      Remove() DeleteOnSubmit()

      RemoveAll() DeleteAllOnSubmit()



      위의 표는 Beta에서 RTM로 버전 업 되면서 변경된 매서드 들입니다. 참고 하세요..



      4. 데이터의 수정 및 삭제



      데이터를 수정하거나 삭제하기 위해서는 가장 먼저 수정이나 삭제를 하기 위한 데이터를 가져와 entity 개체를 생성해야 합니다.



      Post post;

      int postId = Convert.ToInt32(Request.QueryString["postid"]);

      if (postId > 0)

      {

      post = db.Posts.Single(p => p.PostID == postId);

      }

      데이터의 삽입과 마찬가지로 entity개체의 각 속성에 값을 할당합니다.



      post.Title = txtTitle.Text;

      post.Content = txtContent.Text;

      post.PubDate = DateTime.Now;

      post.CategoryID = Convert.ToInt32(ddlCategory.SelectedItem.Value);

      값을 모두 할당 한 다음 변경된 값을 처리하기 위해 BlogDataContext의 SubmitChanges 매서드를 호출하여 수정을 완료 합니다.



      db.SubmitChanges();

      데이터 삭제의 경우는 entity개체를 생성한 후 db개체의 DeleteOnSubmit매서드를 호출 하기만 하면 삭제 처리가 이루어 집니다.



      5. 쿼리구문의 용법 및 컨트롤 데이터 바인딩



      지금부터 조금 더 다양한 LINQ 쿼리 구문을 이용하여 데이터를 가져오고 또한 가져온 데이터를 ListView컨트롤에 바인딩 하는 방법을 블로그의 매인 페이지를 만들면서 보다 자세히 설명하도록 하겠습니다.





      블로그의 메인페이지는 왼쪽 카테고리 영역과 오른쪽 포스트목록 영역으로 나누도록 하겠습니다.

      이 두 부분은 .Net Frameowrk3.5에서 새롭게 등장한 ListView컨트롤을 사용하고 있습니다.


















    • ">






    • ListView컨트롤의 사용법은 본 강좌의 주제에서 벗어나기 때문에 간단하게 설명 하도록 하겠습니다.

      ListView컨트롤은 간단히 LayoutTemplete과 ItemTemplete영역으로 나눌 수 있는데 LayoutTemplete은 목록의 헤더 또는 목록을 감싸는 Tag를 지정하여 기본 Layout을 지정하는 영역입니다. 반복되는 데이터를 표현하는 부분을 PlaceHolder를 통해 지정해주고 이 컨트롤의 아이디를 ListView컨트롤의ItemPlaceholderID속성에 지정합니다.

      ItemTemplete영역은 실제 반복되는 부분을 만들어 줍니다. 데이터는 Eval매서드를 통해 지정해 줍니다. 이곳에서 반복적으로 생성된 코드가 LayoutTemplete의 PlaceHolder컨트롤에 표현됩니다.



      다음으로 데이터를 ListView컨트롤에 바인딩 하는 코드는 아래와 같습니다.



      List categories = db.Categories.ToList();

      categoryList.DataSource = categories;

      categoryList.DataBind();

      코드는 DropDownList에 데이터를 바인딩 했을 때와 상당히 유사합니다. 다른 점은 ToList() 확장 매서드를 사용하여 반환 타입을 List타입으로 한다는 것입니다.





      쿼리구문은 기본적으로 IQueryable형태로 만들어 지게 됩니다. 이 타입은 루프를 돌면서 값을 사용하기 시작할 때 실제 DB와 통신을 하여 값을 가져오게 됩니다.

      위의 이미지에서도 확인 되듯이 디버그를 해 보면 var categories 부분 에서는 아무런 데이터를 받아 오지 못하고 DataSource에 값을 할당 하였을 때 비로소 데이터를 받아 온 것을 볼 수 있습니다.





      위의 코드는 ToList() 확장 매서드를 사용한 경우인데 이때는 categories변수에 마우스를 올리자 바로 값을 받아 온 것을 확인 할 수 있습니다.

      ToList(), ToArray()와 같은 확장 매서드를 사용하면 데이터의 타입을 변경하는 동시에 즉시 데이터베이스와 통신을 하여 값을 받아 올 수 있습니다.



      마지막으로 Where구문을 사용하여 조건 별로 데이터를 가져오고 Skip과 Take확장 매서드를 사용하여 페이징을 처리 하는 부분에 대해 알아보도록 하겠습니다.





      1) 조건 절을 이용한 데이터 조회 및 정렬(단일 포스트 가져오기)



      List posts = (from p in db.Posts

      where p.PostID == postid

      orderby p.PubDate descending //정렬

      select p).ToList();

      위의 코드에서는 where절을 사용하여 PostID값을 비교하여 데이터를 가져오며 orderby절을 이용하여 PubDate를 기준으로 내림차순으로 정렬합니다.



      2) 페이징(한 화면에 보여 줄 포스트들을 가져오기)



      List posts = (from p in db.Posts

      orderby p.PubDate descending

      select p).Skip(currentPageIdx * itemCount).Take(itemCount).ToList();

      PubDate를 기준으로 정렬 하며 Skip확장 매서드를 통해 [현재페이지번호*한 페이지의 항목 수]만큼을 skip하고 Take확장 매서드를 사용하여 한 페이지의 항목 수 만큼 가져옵니다.



      3) 조건 절과 페이지을 모두 이용한 데이터 조회(카테고리 별 목록을 페이징을 통하여 가져오기)



      List posts = (from p in db.Posts

      where p.CategoryID == categoryid

      orderby p.PubDate descending

      select p).Skip(currentPageIdx * itemCount).Take(itemCount).ToList();

      위에서 가져온 데이터를 ListView컨트롤에 바인딩 하기 위해 ListView컨트롤을 구성하면



      // Category영역































    • // 포스트 영역


















      블로그 포스트 영역에서는 LayoutTemplate에 PlaceHolder컨트롤을 추가하고 ItemTemplete에 제목영역과 설명영역(발행일, 카테고리, 수정버튼), 컨텐츠 영역을 각 div태그로 생성합니다.

      데이터는 Eval매서드를 통하여 지정을 하는데 여기서 특이한 점은 부분에서 CategoryName을 가져오는 것입니다. Post테이블에는 CategoryID만 존재할 뿐 CategoryName은 존재하지 않는데 위의 코드에서는 CategoryName을 지정해 줬다는 것입니다. 이는 Post테이블이 CategoryID속성을 통해 Category테이블과 연관관계를 맺고 있으므로 Post의 Category개체를 통해 CategoryName에 접근 할 수 있게 되는 것 입니다.



      카테고리 영역에서는 Unorder List(UL)태그를 ListView컨트롤에 사용하여 카테고리 역영을 생성합니다. LayoutTemplete영역을
        태그로 구성하고 반복데이터가 표현될 영역을 PlaceHolder컨트롤로 지정합니다. ItemTelplete영역은
      • 태그를 사용하여 반복되는 데이터를 표현합니다.

        ListView컨트롤은 반드시 테이블 형태가 아닌 어떠한 반복 구조도 표현 할 수 있는 장점이 있습니다.



        이번 글에서는 LINQ to SQL의 간단한 사용법에 대해서 알아 보았습니다. '어떻게 LINQ to SQL을 사용할 수 있는 가'에 초점을 맞추었기 때문에 LINQ의 일반적인 사용법에 대해서만 알아 보았습니다. 다음 강좌는 다양한 쿼리구문과 Lambda Expression 예제를 통해 LINQ에 대해 보다 자세히 알아보도록 하겠습니다.



        그럼 다음강좌에서 다시 뵙도록 하겠습니다.^^ 감사합니다.















    댓글 없음:

    댓글 쓰기

    국정원의 댓글 공작을 지탄합니다.

    UPBIT is a South Korean company, and people died of suicide cause of coin investment.

     UPBIT is a South Korean company, and people died of suicide cause of coin. The company helps the people who control the market price manipu...