'.Net Framework 3.0'에 해당되는 글 4건

  1. 2008/04/16 글뻥 LINQ에 대한 기록 - 3
  2. 2008/04/04 글뻥 VS2008에서 오라클 클라이언트를 필수 구성요소로 추가해 Clickonce로 배포해보자 (3)
  3. 2008/03/29 글뻥 LINQ에 대한 기록 - 2
  4. 2008/03/02 글뻥 LINQ에 대한 기록 - 1

본격적인 LINQ 실행을 함 해보자.
예고와는 다르게 일단 XML부터 Linq를 통해 한번 제대로 굴려보도록 하자.

1. XML 파싱하기.
먼저 다음과 같이 XML파일 하나 만들어 보자
(파일명은 test.xml로 하자.)

<?xml version="1.0" encoding="utf-8" ?>
<config>
   <id>111.111.111.111</id>
   <user>vic</user>
   <pass>password</pass>
</config>

일반적으로 많이 만들어 사용하는 콘피그 파일이다.
Linq이전에는 이녀석을 비교하려고 XML Document 열어서 열심히 While문으로 Read했었다.
Linq로 이놈을 한번 분석해보면 다음과 같이 매우 짧게 진행할 수 있다.

using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;

class Test {   static void Main(){    XDocument xe = XDocument.Load(System.Windows.Forms.Application.StartupPath  + "\\test.xml");     var query = from c in xe.Descendants("config")                     select c;

   foreach(var q in query)    {       Console.WriteLine(q);    }    Console.ReadLine();   }  }


실행시켜보면 위의 XML전체가 출력되는 것을 볼수 있을 것이다.
이제 이녀석을 좀더 다듬어 보자.
"select c;"라고 된 부분을 "select c.Element("id");"로 바꿔보자.
    var query = from c in xe.Descendants("config") 
                    select c.Element("id");

실행을 하면 XML의 ID부분만 출력이 될 것이다.
<id>111.111.111.111</id>

어쩐지 제대로 찾아 들어오는 느낌. 이제 아까 바꾼 "select c.Element("id");"를
"select c.Element("id").Value;"로 바꿔보자.
    var query = from c in xe.Descendants("config") 
                    select c.Element("id").Value;

실행하면 결과가 아주 이쁘게 값만 떨어진다.
111.111.111.111

그런데 여기서 만족할 수 없다. 여러개의 값을 가려오려면 어떻게 해야 할 까?
다음과 같이 함 바꿔보자.

    var query = from c in xe.Descendants("config") 
                    select new 
                    {
                        id = c.Element("id").Value,
                       user = c.Element("user").Value
                     }
   //이번에는 foreach문도 바꿔주자
   foreach(var q in query)
   {
      Console.WriteLine(q.id + q.user);
   }   

결과는 직접 함 해보도록하고 이제 다음단계로 SQL문처럼 한번 써보자.
다음과 같이 바꿔보고 실행 함 해보자.
    var query = from c in xe.Descendants("config") 
                where c.Element("user").Value == "vic"
                select c;

어떤게 나오는가? where문이 진짜 먹으니 뿌듯한 느낌!

2. XML생성
이제 한걸음 더 나가서 XML을 생성함 해보자.
사용은 무지 쉽다.
using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;

class Test {   static void Main(){   XDocument xdoc =       new XDocument(       new XDeclaration("1.0", "UTF-8", "yes"),       new XProcessingInstruction("TEST", "TEST Data"),       new XComment("테스트 XML"),       new XElement("config",           new XElement("id", "1234"),           new XElement("user", "abc")       )            );    xdoc.Save(System.Windows.Forms.Application.StartupPath  + "\\test.xml");   }  }



test,xml을 열어 보면
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<?TEST TEST Data?>
<!--테스트 XML-->
<config>
  <id>1234</id>
  <user>abc</user>
</config>

이렇게 정확하게 들어와 있는 것이 보일것이다.

2008/04/16 13:09 2008/04/16 13:09

Visual Studio를 사용하면서 Clickonce 배포를 한번이라도 해본 프로그래머라면 이런 화면 기억할 것이다.

사용자 삽입 이미지

Clickonce로 배포하기전에 사용자 클라이언트에 대한 설정을 해두면 다음과 같이 설치화면에서 자동으로 감지하여 추가 설치프로그램을 다운로드하여 설치한다.
사용자 삽입 이미지
* 게시자와 프로젝트는 임의로 제거하였으니 양해바랍니다.

아무튼 뭔가 좀 있어보인다.
특히 오라클과의 연동을 위해서는 필수적으로 Oracle Client가 깔려야 하고 그위에 나머지 DB Connection이나 기타 등등의 모듈이 올라가야 정상적으로 작동되는데 웹으로 배포하면서 Oracle Client는 CD로 들고 다니거나 사용자에게 어디어디서 받으라고 시키는 것은 웃기는 방법 아닐까?

* 주의! : 본 프로그램은 인트라넷에서 사용을 목적으로 철저히 통제된 환경이므로 가능하나 인터넷 서비스하는데 오라클 설치 시키는 바보는 없겠지? 인터넷에서는 SOAP 프로토콜을 활용하자.

아무튼 Clickonce 배포방식을 선택했다면 그에 맞도록 개발하려는 노력도 필요할것이고 그보다 우선하여 이와 같은 방식을 Framework에서 지원하여야 하는 것이다. 다행히 DotNetFramwork는 지원하고 있으므로 문제될 것이 없다. 이제 남은 것은 방법을 알고 실행에 옮기는 것 뿐이니 말이다.

1. 먼저 Oracle Client를 설치 파일로 만들자.
예전에 포스팅한 http://www.wolfpack.pe.kr/210를 참고하여 오라클 클라이언트 라이트 버전의 설치와 사용법을 먼저 숙지하자. (꼭 먼저 읽어 보아야 다음 설치파일 만들기가 이해될 것이다.)
다했다면 다음과 같이 설치 프로젝트로 Visual Sudio를 열자.
사용자 삽입 이미지

이름을 아무거나 주면 된다.
프로젝트가 생성되고나면 Oracle Lite Client 가 설정 되어 있는 경로의 파일들을 몽땅 추가해놓자.
사용자 삽입 이미지
다음은 추가해 놓은 모습으로 오라클 명령을 수행하는데 전혀 지장없는 것들은 남겨 놓고 불필요한것들은 삭제한후에 정리해서 넣어놓은 것이다.
사용자 삽입 이미지
추가가 되었다면 프로젝트 속성창에서 설치될 경로를 지정하자. 속성은 다음과 같이 프로젝트명을 우클릭한후 "보기", "파일시스템"을 클릭하고 파일시스템의 속성을 수정하면 된다.
사용자 삽입 이미지
사용자 삽입 이미지
* 기본 DefaultLocation을 "c:\program files\OCI"로 설정하였다.

설치될 Oracle Client의 레지스트리 파일을 수정할 차례이다.
위와 같은 방법으로 프로젝트명을 클릭한후 우클릭하여 "보기", "레지스트리"를 클릭하자.
사용자 삽입 이미지
다음과 같이 HKEY_CURRENT_USER에 "Environment"라는 키를 만들고 다음과 같이 "LD_LIBRARY_PATH", "Path", "TNS_ADMIN"을 설정한다.
사용자 삽입 이미지
위의 최종 화면을 보면서 다음과 같이 하면 간단히 해결된다.
먼저 Path를 설정해보자. 빈 화면에서 우클릭하여 "새로 만들기", "확장 가능한 문자열 값"을 선택한후에 이름을 "Path"라고 하고 속성창에서 Value부분을 추가한다.
사용자 삽입 이미지
사용자 삽입 이미지
사용자 삽입 이미지
나머지 2개 "LD_LIBRARY_PATH", "TNS_ADMIN"도 추가하되 "Path"와는 다르게 "문자열 값"으로 설정하자.
사용자 삽입 이미지
속성과 키값은 "Path"설정과 동일하다. 단지 속성은 "c:\program files\oci"로 설치경로와 동일하게 진행하면 된다.

"F6"를 눌러서 솔루션을 빌드하자.
빌드한후 "탐색기"나 "내컴퓨터"로 보면 다음과 같이 얌전히 msi파일이 만들어져 있다.
사용자 삽입 이미지

2. 만들어진 파일을 필수구성요소 중 하나로 설정하자.
만들어진 msi파일을 clickonce의 필수 구성요소로 지정하려면 이녀석이 필수 구소요소에 해당하는 것이지 알아야 Visual Studio에서 이러한 것들이 있어요~ 라고 나열해 줄수 있을 것이다.
다시말해 어떤 저장소가 있고 그 저장소에 있는 파일들을 나열해주지 않았을까?
함 찾아 보자.
Visual Studio 2008을 설치했다면 "C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages"로 이동해보자.
(그 이전버전의 경우는 "C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0" 밑에 Bootstrapper에 Packages에 있었나?? 암튼 그랬으니 찾아보자.)

그런데 여기다 놓는 것으로만 끝나는 것이 아니라 이녀석이 설치될 환경을 지정해줘야 할것 아닌가? 여기서 문제가 발생하는데 이 환경설정이라는 것이 매우 아주 짜증나게 복잡하고 어렵다.
Visual Studio에서도 지원하지 않는 기능이다보니 짜증난다. 이럴때는 3rd Part 프로그램을 찾아보는 것이 현명하고 또 마침 좋은 녀석이 있다.
"Bootstrapper Manifest Generator"라는 녀석이고 공식홈에서 쉽게 다운로드 할 수 있으니 본 블로그의 계정용량을 생각하여 첨부는 생략한다. 공식홈은 여기로 : http://www.codeplex.com/bmg

VS2005용 : http://www.codeplex.com/bmg/release/pr ··· d%3D2215
VS2008용 : http://www.codeplex.com/bmg/release/pr ··· %3D10652

다운로드후 설치하고 "C:\Program Files\Microsoft\Bootstrapper Manifest Generator for VS2008"에 "BMG.EXE"라는 놈을 실행하면 된다. (덴장. 바로가기 버튼이라도 만들어 줄것이지..)

실행하면 다음과 같이 열리는데 Project Name과 Product Code만 "OCI"로 입력하였다.
사용자 삽입 이미지
Package를 우클릭한후에 "Add Install File"을 선택하자
사용자 삽입 이미지
파일을 설정한후 다음과 같이 설치파일에 대한 정보를 설정하였다.
- Display Name : Oracle Client
- Language : 한국어
- Properties 에 Reboot을 None으로 설정하였고 Installation Time을 "30"으로 잡아 줬다.
사용자 삽입 이미지
"System Checks"탭으로 이동하여 왼쪽 상단의 File Check를 추가하고 다음과 같이 지정한다.
Property for Result - Installed
File Name to Search - 찾기로 설치 될 파일중 하나를 지정
Start Searche in Special Folder 체크 해제
Path - 설치될 경로
사용자 삽입 이미지
Install Conditions로 이동해서 다음과 같이 ByPassIf로 설치안하고 통과할 조건을 설정하자.
사용자 삽입 이미지
이제 마지막 설정단계이다. Use Default System Exit Codes 부분을 체크해제하자.
사용자 삽입 이미지
모든 설정이 완료 되었으면 Build한다.
사용자 삽입 이미지
빌드 화면인데 Error나 Warning 없이 완료되었다는 메시지가 뜬다.
사용자 삽입 이미지
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages"밑에 "OCI"라는 폴더가 만들어져 있고 그 안에 보면 product.xml이라는 이름으로 설치파일에 대한 기본정보가 생성되었다.
- product.xml
<?xml version="1.0" encoding="utf-8"?>
<Product ProductCode="OCI" xmlns="http://schemas.microsoft.com/developer ··· strapper">
  <RelatedProducts>
    <DependsOnProduct Code="Microsoft.Windows.Installer.3.1" />
  </RelatedProducts>
</Product>

그리고 "ko"라는 한국어 설치본이 저장되는 폴더가 생성되어 있고 거기를 또 들어가면 "package.xml"과 "oci.msi"파일이 생성되어 있다.
-package.xml
<?xml version="1.0" encoding="utf-8"?>
<Package Name="DisplayName" Culture="Culture" xmlns="http://schemas.microsoft.com/developer ··· strapper">
  <PackageFiles CopyAllPackageFiles="false">
    <PackageFile Name="oci.msi" Hash="CCA799724D75045AC38679C86C93AE2F890E37A7" />
  </PackageFiles>
  <InstallChecks>
    <FileCheck Property="installed" SearchPath="c:\program files\oci" FileName="oraociei10.dll" />
  </InstallChecks>
  <Commands Reboot="None">
    <Command PackageFile="oci.msi" EstimatedInstallSeconds="30">
      <InstallConditions>
        <BypassIf Property="installed" Compare="ValueGreaterThanOrEqualTo" Value="0" />
      </InstallConditions>
    </Command>
  </Commands>
  <Strings>
    <String Name="Culture">ko</String>
    <String Name="DisplayName">Oracle Client</String>
  </Strings>
</Package>

* 아직 베타판인 VS 2008용 Bootstrapper 생성프로그램의 경우 저장을 해도 제대로 불러 오지 못하는 심각한 버그가 있으나 생성까지는 잘되니 눈감고 써주자.

3. Clickonce에 필수파일로 지정하자.
만드는 것까지 완료했다면 실재 사용해봐야 할것아닌가?
Clickonce로 배포할 프로그램이 있다면 프로젝트 속성창에 게시탭을 클릭하여 "필수구성요소"를 선택하자.
사용자 삽입 이미지
이제 가슴 떨리는 순간 두근거림과 함께 우리가 생성한 Oracle Client가 보이면 되는것이다.
다행히 Oracle Client가 포함되어 있다. 배포할때 응용프로그램과 같이 배포하면 될것이니 "내 응용 프로그램과 동일한 위치 ~ 다운로드"를 선택하고 확인을 누른다.
사용자 삽입 이미지
만약 보이지 않는다면 저장소 정보 갱신이 늦어졌을터이니
뻐그 많은 "Bootstrapper Manifest Generator"를 띄워서 "Generate Package Installer"를 실행하여 업데이트를 해주자.
사용자 삽입 이미지

휴~ 이제 완료 된것 같다. 써놓고 보니 가히 사용자 지정 필수 구성요소 추가하기 집대성인듯 싶다.
국내최초의 Visual Studio 2008 대상의 사용자 정의 필수 구성요소 추가하기에 대한 글을 읽어주신 여러 블로거들에게 감사를 보낸다.
2008/04/04 10:57 2008/04/04 10:57

흠... 좀 길었다. linq에 대한 기록중 약속한 첫번째 C# 3.0의 변화 부분을 살펴 보자.
(컴파일러는 .NET Framework 3.5 로 테스트하였다.)

1. "var" (Local Variable Type Inference) 변수 지원
var는 정말 불확실성때문에 꺼려지는 문법중하나이다. 그러나 MS가 누구인가?
VB부터 줄곧 따라다니던 VAR를 포기하나 했더니 결국 집어 넣고 말았다.

//여기서부터
using System;
class Test {
  public static void Main() {
    var a = "12345";
    Console.WriteLine (a);
    var b = 123456;
    Console.WriteLine (b.ToString());
  }
}

컴파일 부터 실행까지 아무런 문제 없이 실행된다. -_-
단, var를 실행되는 런타임이 결정하는 것이 아니라 컴파일하는 컴파일러가 결정한다.
따라서 null을 넣게 되면?
"test.cs(4,9): error CS0815: 암시적으로 형식화된 지역변수에는 <null>을 할당 할 수 없습니다."라는 메시지를 보게될 것이다.
이부분이 가장 중요한 부분이다. 왜냐면 다른 특징들은 모두 var를 지원함으로써 얻어지는 것이기 때문이다.

2. 자동화된 get/set
클래스의 특징을 설명하며 클래스의 값을 주고 받을 때 어떻게 하는지 인터페이싱을 어떻게 해야하는지에 대해 설명할때 다른 언어와의 차별점으로 OOP에서는 GET/SET명령을 통해 인터페이스 한다고 아주 오래전에 설명한적이 있다. 그런데 이게 사실 꽤나 노가다 이다.
* 예전글은 여기서 : http://www.wolfpack.pe.kr/73

using System;
class Test {
  public static void Main() {
    a ar = new a();
    ar.AA="abcdef";
    Console.WriteLine ("인터페이스결과:"+ar.mthod());
  }
}

public class a{     //GET; SET; 사용을 자세히 보자     public string AA{ get; set; }      public string mthod(){         return AA;     } }


"바로 여기를 어쩌구 저쩌구 줄었다!"라는 부분을 보면 클래스의 Entity AA 선언자체가 get/set 딱 1줄로 팍 줄어 있다. 이전 버전에서라면 이렇게 길었는데 말이다.
//참고용으로 .NET Framework 2.0 이전 버전임
public class a{
    private string aa;
    
    public string AA{
      get{
          return aa;
      } 
      set{
          aa = value;
      } 
    } 

    public string mthod(){         return aa;     } }


* 참고로 Readonly선언의 경우는 set 을 private로 변경해준다.
예 : public string AA{ get; private set; }

3. 객체 / 배열 인스턴스의 변경
다음의 코드는 "2번"항목의 코드를 C# 3.0의 변화에 맞게 수정한 것이다.

using System;
class Test {
  public static void Main() {
    a ar = new a { AA="abcdef" };
    Console.WriteLine ("인터페이스결과:"+ar.mthod());
  }
}
public class a{
    public string AA{ get; set; } 
    public string mthod(){
        return AA;
    }
}

즉, 기존에 인스턴스화할때 다음과 같이 하던 부분을 선언과 동시에 값을 넣을수 있도록 변경되었다.
//2.0용
a ar = new a();
a.AA="abcdef";

//3.0용 a ar = new a { AA="abcdef" };

또한 배열도 마찬가지로 이렇게 사용하는 것이 가능하다.

int[] scores = new int[] { 97, 92, 81, 60 };

4. 배열, XML, DB 등 데이터를 가져오는 것이 하나의 방법으로 통한다.
바로 이부분이 LINQ의 능력이다.
배열이나 XML, DB등 데이터를 가져와서 핸들링 할때 데이터를 가져오는 부분이 모두 달랐다.
XML을 파싱해서 각각의 변수에 넣었다가 핸들링하고 다시 집어 넣고 노가다 였는데 모든 것을 Linq 한방에 핸들링 할 수 있다는 것이다.

using System;
using System.Linq;

class Test {   public static void Main() {       int[] scores = new int[] { 97, 92, 81, 60 };

      var scoreQuery =  from score in scores                                where score > 80                                select score;

      foreach (int i in scoreQuery)       {           Console.Write(i + " ");       }              } }


배열인 scores에 대해 80점 이상인 놈만 가져오자. 이런거 할려면 if문 넣어서 뺑뺑이 돌리던 기억이 엇그제 같은데 LINQ로 한방에 끝나버린다.

5. Anonymous Type을 지원한다.
다음의 황당한 코드 함 보자.

using System;

class Test {   public static void Main() {       var user = new { Name = "vicviper", Age = 35 };       Console.WriteLine (user.Name);   } }


무엇이 황당한가? 분명 2.0대에서는 user라는 클래스를 만들고 Name과 Age를 인터페이스 선언하여야 정상 작동하던 코드였다. 그러나, 우리의 C# 3.0 컴파일러는 이렇게 단순한 놈은 자동으로 생성해버린다.
따라서, 컴파일러 오류도 없고 정상작동되는 것이다. 심지어 이런것도 가능하다.
using System;

class Test {   public static void Main() {       var family1 = new { Name = "papa", Age = 35 };       var family2 = new { Name = "mama", Age = 35 };       Console.WriteLine (family1.Age + family2.Age);   } }

마치며.
결론적으로 C# 3.0은 코딩량을 줄여준다는 점에서 점수를 줄만하다.
그러나 OOP가 아니었다면 원래 안해도 되는 일을 OOP의 논리때문에 코딩량이 는것아닌가?
아마도 OOP원리주의자들이 이러한 C# 3.0의 변화를 본다면 분명 이게 무슨 OOP냐고 되물을 것이다. 그러나, 프로그래머도 인간이다.
인간이기에 편해지려는 노력을 하는 것이고 편해지기위해 새로운 방법을 찾는다.
현재로써는 C# 3.0은 당연히 되어야 하는 부분을 하나씩 지원해주는 느낌이다.


2008/03/29 16:15 2008/03/29 16:15
어느날 문득. 눈을 떴을때 VS2008의 릴소식과 함께 들리는 LINQ.
물론 나는 굉장히 회의적인 입장이며 이러한 잦은 버전업 자체가 개발자들을 피곤하게 한다는 것에 문제를 제기하고자 하는것이다.

물론 .NET Framework 3.0에 대해 2004년 쯔음부터 냄새가 솔솔 올라 오기 시작했으니 그리 짧은시간이 걸린것은 아니나 그렇자도 피곤하지 않다는 것은 절대 아니다.
(Silverlight를 보자. 1.0이 2008과 함께 릴된지 얼나마 됐다고 벌써 2.0 준비중이란다 -_-;;)

아무튼 가장 큰 변화중에 하나인 LINQ를 짚고 넘어가지 않으면 안되는 이유가 LINQ로 인하여 너무나도 많은 것이 변화되어 버렸기에 짚고 넘어가야만 한다.

먼저 LINQ의 아키텍쳐를 보도록 하자.
사용자 삽입 이미지
조금 작긴하지만 LINQ로 할 수 있는 것은 object, Dataset, SQL, Entities, XML 이렇게 5가지이며 Object와 RDB, XML 3가지에 대해 컨트롤 할 수 있게 되었다.

다시말해 3tire 시스템에서 맨 끝에 존재하는 현존하는 데이터 영역 모두를 LINQ를 통해 단일화된 방법으로 사용할 수 있는 것이다.
(생각해보자 그전에 Data Object, DB, XML 3가지의 사용법이 모두 달라 얼마나 힘들었는지?)

또한 LINQ를 활용하여 delegate 대리자를 선언하지 않아도 되며 OR Mapping 툴 또는 Framework를 별도로 설치하지 않아도 된다.

뭐 암튼 좋단다. 뭐가 좋은지 이제 하나씩 까보도록 해보자.
물론 MS꺼다! 무슨 말인지 다들 알죠?

이랬던 것이
사용자 삽입 이미지

이렇게 작동되는 뻐그들은 여전히 있다.
사용자 삽입 이미지
(니미...)


- 목차
0. 잡설
1. C# 3.0의 변화
2. LINQ to Object
3. LINQ to Database
4. LINQ to SQL
5. LINQ to Entities
6. LINQ to XML
2008/03/02 16:48 2008/03/02 16:48