'분류 전체보기'에 해당되는 글 189건

  1. 2009.05.07 C# 코딩 연습 - 크로스 스레드와 Control.Invoke 4
  2. 2009.05.07 개발용 무료 SSL 인증서를 만드는 4단계 방법
  3. 2009.04.30 비주얼 스튜디오 설치 프로젝트에 닷넷 프레임웍을 필수 구성요소로 추가하는 방법
  4. 2009.03.30 실버라이트 3의 새 기능 가이드
  5. 2009.03.26 LINQ 심층 분석 : 쿼리 연산자의 입력과 출력
  6. 2009.03.25 Midnight Peach 2.0 샘플 애플리케이션, 웹 애플리케이션 (2/2)
  7. 2009.03.25 C# CAPTCHA(자동가입방지용 이미지) 라이브러리
  8. 2009.03.25 문자열을 64비트 정수로 변환하는 메서드
  9. 2009.03.25 토픽 기반의 발행자/구독자 디자인 패턴 구현
  10. 2009.03.24 SQL Server 2008 Management Studio의 새로운 기능

C# 코딩 연습 - 크로스 스레드와 Control.Invoke

C# 코딩 연습 2009. 5. 7. 14:05

명작 도서 More Effective C#: 50 Specific Ways to Improve Your C#를 읽다 보니 Control.Invoke를 캡슐화 한 ControlExtensions 이라는 클래스에 대한 이야기가 나왔습니다.

원서에는 멀티 스레딩이나 크로스 스레드 등에 대한 배경 설명 없이 달랑 몇 줄의 코드 정도만 제시되어 있는데 (이것이 바로 이 책의 매력 –반어적 의미 아님- 입니다.),

여기에 앞 뒤 설명을 붙이고, 간단한 예제를 만들어 보았습니다.


매 1초 마다 현재 시각을 표시하는 간단한 시계를 만든다고 합시다.

보통은 System.Timers.Timer 나 System.Threading.Timer, 혹은 System.Windows.Forms.Timer 를 사용하겠지만, 여기서는 Thread.Sleep 메서드를 이용하여 매 1초 마다 시간을 표시하는 방법을 사용해 보겠습니다.

실행하면, 시작하자 마자 바로 화면이 먹통이 되어버리는 걸 알 수 있습니다.

Thread.Sleep 메서드가 현재 메서드(UI가 생성된 메서드)를 잡고 있는 이른바 UI 블로킹이 일어난 것인데요. 이를 해결하기 위해서는 이 부분을 별도의 스레드에서 실행하여야 합니다.

1초를 기다린 후 라벨에 시각을 표시하는 로직이 별도의 메서드(StartNewThread)로 빠졌고, 이 메서드는 이제 메인 스레드(UI 스레드)와는 별개의 스레드에서 실행됩니다.

실행을 해 봅시다. 디버깅하지 않고 시작(CTRL + F5)을 실행하면 (운이 좋다면) 문제 없이 시계가 동작하는 걸 볼 수 있지만, 디버깅 시작(F5)을 실행하면 label1.Text = DateTime.Now.ToString();

에서 InvalidOperationException가 발생합니다.

일명 크로스 스레드 예외라고 하는데요.

label1.Text = DateTime.Now.ToString(); 에서 라벨 컨트롤에 접근을 하려고 하는데, 문제는 이 코드가 실행되는 스레드가 라벨 컨트롤이 생성된 스레드(메인 스레드, UI 스레드)가 아니라는 것입니다.


Control.Invoke를 호출하는 방법과 BackgroundWorker를 사용하는 두 가지 방법이 있을텐데, 대부분의 경우에는 BackgroundWorker 가 좋은 선택이 될 것입니다.

스레드 간에 상태를 공유하고, 진행상황을 보고하고, 작업을 중지하는 등 스레드와 관련한 대부분의 작업이 이미 구현되어 있기 때문에 편리하게 사용할 수 있습니다.

다만 BackgroundWorker에는옥의 티랄까, 한 가지 알려진 버그가 있습니다.

이 포스트의 주제가 BackgroundWorker가 아니고, 또 BackgroundWorker에는 곁다리로 슬쩍 이야기할 수 있는 수준 이상의 논점이 많으니까, 이 포스트에서는 Control.Invoke에 대해서만 이야기하도록 하겠습니다.


Control.Invoke를 호출하여 크로스 스레드 문제를 해결하는 코드는 다음과 같습니다.

먼저 라벨의 InvokeRequired 를 체크하여 Invoke가 필요한지를, 즉 컨트롤에 접근하는 스레드와 컨트롤이 생성된 스레드가  다른 스레드인지를 체크합니다.

굳이 Invoke가 필요하지 않다면 (비록 미미하더라도) 비용이 드는 Invoke를 호출할 필요가 없을 것입니다.

Control.Invoke의 시그니처는 다음과 같습니다.

첫번째 매개변수가 추상 클래스인 Delegate입니다.

따라서 label1.Invoke(new Delegate(DisplayDateTime)); 과 같이 대리자 인스턴스를 생성할 수가 없습니다.

대신 DisplayDateTimeHandler 라는 대리자 형식을 정의한 후 이 인스턴스를 전달하여야 합니다.

이제 실행(디버깅)을 하여 보면 크로스 스레드 문제 없이 잘 동작합니다.


크로스 스레드 문제가 해결되었으니 여기서 포스트가 끝나야 할 것 같지만, 이 포스트를 서야겠다고 생각한 이유는 사실은 지금 부터 시작 합니다.

Control.Invoke를 호출하는 위 코드를 Action 대리자와 확장 메서드를 사용하여 필드에서 사용할 만한 라이브러리로 만들어 봅시다.


닷넷 프레임웍 2.0에 추가된 두 가지 제네릭 대리자를 사용하면 대부분의 경우에는 대리자를 작성할 필요가 없습니다.

Func과  Action 대리자가 그것인데요. Func은 반환값이 있지만 Action은 반환값이 없다는(void) 점 외에는 동일하며, 두 대리자 모두 매개변수가 0개 ~ 4개인 오버로드가 각각 준비되어 있습니다.

(정확하게 이야기하자면, 매개변수가 0개인 Action 대리자의 형은 void Action() 이므로 제네릭 대리자는 아닙니다.)

그래서 매개 변수가 4개가 넘지 않는 시그니처를 가지는 대리자는 이 두 대리자로 표현할 수가 있는 것입니다.

위 코드에서도 DisplayDateTimeHandler 대리자를 따로 정의하지 않고 제네릭 대리자를 사용할 수 있습니다.

반환값이 없고 매개변수도 없으니까, 제네릭이 아닌 Action 대리자를 사용하면 되겠습니다.


이번에는 확장 메서드를 사용하여 위 코드를 캡슐화 해봅시다.

ControlExtensions라는 static 클래스를 만들고 아래와 같은 확장 메서드를 추가합니다.

(여기서는 매개변수가 0개 ~ 1개인 오버로드만 보이는데, 2개 ~ 4개인 오버로드도 정의해두면 편리합니다.)

이제 StartNewThread 메서드는 아래와 같이 간단해 집니다.

 

람다식이나 익명 메서드를 이용하면 DisplayDateTime 메서드도 따로 정의할 필요가 없어 코드가 좀 더 간단해 집니다.


연습 삼아 코드를 약간 고쳐 봅시다.

DisplayDateTime 메서드를 매개 변수를 가지는 형태로 다음과 같이 수정합니다.

그렇다면 이제 라벨의 Invoke 메서드를 호출할 때 현재 시각을 매개 변수로 넘겨야 합니다.

ControlExtensions.InvokeIfNeeded 오버로드 중,

가 호출되는데, 이는 다시 control.Invoke(action, arg); 를 호출합니다.

Control.Invoke의 두 번째 매개변수는 params object[] 이기 때문에, action 대리자의 매개변수의 갯수가 형에 상관없이 호출이 가능합니다.


보너스 : 제가 알렸드렸다고 소문 내지는 마시고, More Effective C# 책이 보고 싶으신 분은 이 링크를 눌러 보세요.

:

개발용 무료 SSL 인증서를 만드는 4단계 방법

RTFM/ASP.NET 2009. 5. 7. 09:38

http://www.codeproject.com/KB/aspnet/4stepsSSL.aspx

 

원문의 제목에는 괄호를 쳐서 “이 문서를 읽으면 100$를 절약할 수 있음” 이라고 적혀 있고 아래와 같은 표를 그 근거로 제시하고 있습니다.

image

코드 프로젝트에 부쩍 인도 개발자들의 아티클이 많아진 것이 최근의 일은 아니지만, 이 아티클의 저자인 Shivprasad koirala는 그 중에서도 단연 눈에 띄입니다.

오늘(2009.5.7 ) 날짜로 현재 코드 프로젝트에 총 72개의 아티클을 게시하였는데, 그 중 대부분이 2008년 하반기 이후에 씌여진 것입니다.

General 카테고리를 제외하더라도 9개의 카테고리에 걸쳐 있으니 다루는 아티클도 무척 다양합니다.

대단한 정력가임이 틀림 없습니다.

 

다만 대부분의 아티클이 기술의 소개에 그치는 정도가 많아 깊이 면에서는 약간의 아쉬움이 있다는 사견, 덧붙입니다.

:

비주얼 스튜디오 설치 프로젝트에 닷넷 프레임웍을 필수 구성요소로 추가하는 방법

RTFM/Visual Studio 2009. 4. 30. 10:31

http://www.codeproject.com/KB/dotnet/Add_framework_in_setup.aspx

 

여러가지 방법이 있을 수 있겠으나 이 방법이 가장 깔끔하고 편리하지 않나 싶습니다.

항상 느끼는 것이지만, 설치 프로젝트의 자동 업데이트 기능의 부재가 아쉬울 따름입니다.

:

실버라이트 3의 새 기능 가이드

RTFM/Silverlight 2009. 3. 30. 10:24
:

LINQ 심층 분석 : 쿼리 연산자의 입력과 출력

RTFM/C# 2009. 3. 26. 13:47

http://aspnet.4guysfromrolla.com/articles/032509-1.aspx

 

LINQ의 표준 쿼리 연산자에 대해 깊이 있게 파헤쳐 봅니다.

마지막의 두 단원 (Chaining Query Operators / Query Operators and Deffered Execution)이 특히 유용한데, 예를 들어

// C# - Create an instance of the Fibonacci class to hold the first 7 numbers
Fibonacci fib = new Fibonacci(7);
// Compute the sum of those elements in fib whose preceding elements' sum is greater than or equal to 6
int oddSum = fib.SkipUntilSummationSurpassed(6).Where(x => x % 2 == 1).Summation();

에서, 세 개의 쿼리 연산자의 실행 순서와 그 내부 동작을 설명한 부분과,

욕심쟁이 쿼리 연산자(greedy query operator)와 게으른 쿼리 연산자(lazy query operator)에 대한 설명은 꼭 한번 읽어보실 것을 추천합니다.

:

Midnight Peach 2.0 샘플 애플리케이션, 웹 애플리케이션 (2/2)

Midnight Peach 2009. 3. 25. 23:43

[주의]
이 글은 MP의 현재 버전 (3.X)에 맞지 않습니다.

단순 참고용으로만 활용하십시오

Midnight Peach 2.0 샘플 애플리케이션, 웹 애플리케이션 (1/2)에 이어서 계속 진행하겠습니다.

데이터베이스 연결 문자열

web.config 파일을 열어 데이터베이스 연결 문자열을 설정합니다.

image

여기서 연결 문자열의 이름은 아무렇게나 지정해서는 안됩니다.

MP의 아래 화면에서 지정한 이름과 동일해야 하는데, 여기서는 Memopad로 지정되어 있습니다.

image

연결 문자열을 설정하였으면 DB에 제대로 연결이 되고 생성된 비지니스 레이어에 문제가 없는지 간단히 테스트를 해보도록 합시다.

Default.aspx 파일에 아래와 같은 코드를 입력하고 웹 애플리케이션 프로젝트를 실행하여 봅니다.

image

Memo 테이블의 로우 갯수를 출력하는 코드인데, 샘플 애플리케이션과 함께 배포된 DB에는 10개의 메모가 들어 있습니다.

따라서 10이 출력되면 정상입니다.

MemoList.aspx 페이지

메모들의 목록을 표시하는 페이지를 만듭시다.

프로젝트에 새 아이템을 추가하고 이름을 MemoList라고 합니다.

이 페이지가 하는 일은 다음과 같습니다.

  • 제목으로 검색된 메모 목록을 표시한다.
  • 메모를 클릭하면 해당 메모의 상세화면이 열린다.
  • 페이징을 지원한다.

여기서 약간의 통찰력을 발휘할 필요가 있습니다.

위 요구사항을 보고 필요한 비지니스 로직을 찾아내어, 프리젠테이션 코드와 비지니스 로직 코드를 분리하여야 합니다.

지금은 요구사항이 간단하니까 별다른 고민 없이 다음과 같은 비지니스 메서드가 필요함을 알게 될 것입니다.

image

페이지에서 GetBySubject 메서드가 필요함을 알게되었으니, MemoList 페이지의 작성은 잠시 멈추고 GetBySubject 메서드를 먼저 구현해 보도록 하겠습니다.

필드에서라면 비지니스 로직을 담당하는 개발자에게 의뢰를 하는 형태가 될 수도 있겠지요.

커스텀 비지니스 로직의 구현

여기서부터는 비지니스 로직 담당자의 입장에서 생각을 해봅시다.

GetBySubject란 메서드를 작성하도록 요청을 받았는데, 이 메서드가 하는 일은 ‘제목에 특정 검색어가 포함된 메모들의 목록을 반환하되 페이징을 지원한다’ 입니다.

작성을 해봅시다.

먼저 커스텀 비지니스 로직을 구현하기 위한 클래스를 만들어야 할 텐데, 메모 엔터티에 대한 비지니스 로직이니까 MemoBiz 라는 클래스가 필요할 것입니다.

그런데 사실 이 클래스는 이미 MP가 만들어 놓았습니다.

그렇다면 GetBySubject 메서드를 구현하기 위해 MP가 만들어 놓은 MemoBiz 클래스를 수정하면 될까요?

물론 안될 이유는 없지만, MP가 생성한 코드는 수동으로 고치지 않는 것이 좋습니다.

왜냐하면 나중에 다시 코드가 생성되면 수동으로 추가한 코드가 덮어씌여지기 때문입니다.

대신에 MemoBiz 클래스 파일을 하나 더 추가하고 이를 partial 클래스로 선언하는 것이 정석입니다.

사실 MP가 생성한 모든 클래스는 partial 클래스라서 이러한 방식으로 커스터마이징을 할 수 있습니다.

Memopad.Biz 클래스의 CustomBiz 폴더에 Memo 클래스를 추가합니다.

(물론 CustomBiz 폴더가 아닌 다른 곳에 추가하여도 상관없지만, MP가 추천하는 구조는 CustomBiz 폴더 입니다.)

그럼 프로젝트의 구성은 아래와 같겠네요.

image

추가된 MemoBiz의 코드를 아래와 같이 수정합니다.

image

partial 클래스로 선언하고 네임 스페이스를 MP가 생성한 MemoBiz와 동일하게 맞춰주었습니다.

이제 GetBySubject를 구현합니다.

image

길어 보이기는 하지만 실제 코드는 한 줄입니다.

MemoBiz의 부모인 EntityBiz에 정의된

image

를 다시 호출하고 있습니다.

사실 이 포스트에서 가장 중요한 부분이 여기 입니다.

‘제목에 특정 검색어가 포함된 메모들의 목록을 반환하되 페이징을 지원하는’ 비지니스 메서드를 만드는데, 단 한 줄의 코드만이 필요합니다.

SqlConnection 이나 SqlCommand 객체를 만들 필요도 없으며, DataSet이나 SqlDataReader 같은 클래스는 아예 등장하지도 않습니다.

참고로 [DataObjectMethod(DataObjectMethodType.Select)] 라는 특성은 ObjectDataSource에서 사용되는 특성인데, 이 메서드가 ObjectDataSource의 SelectMethod로 표시되어야 한다는 의미입니다.

이 포스트의 뒤에서 좀 더 자세한 설명을 하도록 하겠습니다.

ObjectDataSource의 구성

다시 MemoList.aspx 페이지로 돌아가서 작업을 계속하도록 하겠습니다.

도구상자에서 ObjectDataSource를 끌어와 페이지에 추가합니다.

추가된 ObjectDataSource의 이름을 odsMemo로 변경한 후 데이터 소스 구성 대화상자를 엽니다.

image

첫번째 단계는 비지니스 객체를 선택하는 것인데, 그림에서 보듯이 선택할 수 있는 객체가 세 가지 밖에 없습니다.

이는 Show only data components 체크박스가 켜져 있기 때문입니다. 즉 이 체크박스가 켜져 있으면 [DataObject] 속성이 붙은 클래스만 이 곳에 표시합니다.

클래스의 수가 수 백개만 넘어도 이 옵션을 켜지 않으면 해당 클래스를 찾기가 힘이 들 것입니다.

참고로 MP가 생성한 비지니스 객체에는 기본적으로 [DataObject] 특성이 붙어 있습니다.

MemoBiz를 선택하고 다음으로 넘어 갑니다.

image

이번에는 SELECT 메서드를 선택합니다.

비주얼 스튜디오는 리플렉션을 통해 SELECT 메서드로 사용할 수 있는 MemoBiz 클래스의 메서드의 목록을 추정하여 보여줍니다.

만일 비주얼 스튜디오의 추정을 통하지 않고 명식적으로 지정하고 싶다면 메서드에 [DataObjectMethod] 특성을 붙여주면 됩니다.

또한 [DataObjectMethod]의 매개변수를 지정함에 따라, 위 그림과 같이 여러 개의 후보 메서드 중에서 기본값으로 지정할 수도 있습니다.

여기서는 위에서 만든 GetBySubject를 선택하고 다음으로 넘어갑니다.

(UPDATE, INSERT,DELETE 메서드에는 이미 기본값이 지정되어 있긴 하지만, 사용하지 않을 메서드이므로 나중에 수동으로 삭제할 것입니다.)

image

마지막으로 GetBySubject의 매개변수를 설정하야 하는데, GetBySubject의 경우에는 특별한 설정이 필요없습니다.

text 매개변수의 경우에는 사실 TextBox 컨트롤에서 값을 읽어오는 것이 정석이겠으나, 여기서는 데모의 목적으로 코드에서 직접 설정하는 방법을 택할 것입니다.

또한 startRowIndex와 maximumRows 이 두 개의 매개변수는 페이징을 위한 것으로서, 나중에 추가할 DataPager 컨트롤이 제어할 값으로 개발자가 직접 제어할 필요가 없습니다.

따라서 그냥 마침을 눌러 ObjectDataSource의 구성을 끝마칩니다.

또한 ObjectDataSource의 InsertMethod, UpdateMethod, DeleteMethod 속성은 사용되지 않으니까 삭제합니다.

ObjectDataSource에 이벤트 추가

이제 ObjectDataSource의 매개변수인 text의 값을 설정하는 코드를 작성할 차례입니다.

text의 값을 설정하기에 가장 적절한 곳은 ObjectDataSource의 OnSelecting 이벤트일 것입니다.

ObjectDataSource의 OnSelecting 이벤트 핸들러를 추가합니다.

(그 전에 txtSearch 라는 TextBox를 페이지에 추가해 두시기 바랍니다.)

image

ObjectDataSource에 페이징 추가

이번에는 ObjectDataSource에 페이징을 추가해 봅시다.

ObjectDataSource에 페이징을 추가하기 위해서는 EnablePaging 속성을 true로 설정하는 것과 더불어 아래와 같이 세 개의 속성을 추가로 지정하여야 합니다.

  • SelectCountMethod
  • StartRowIndexParameterName
  • MaximumRowsParameterName

SelectCountMethod는 전체 로우의 갯수를 반환하는 메서드의 이름입니다.

현재 이런 일을 하는 메서드는 없으니까 새로 만들어야 합니다.

GetBySubject가 정의된 MemoBiz에 GetBySubjectCount 라는 메서드를 만들어 봅시다.

먼저 GetBySubjectCount의 시그니처에 대해서 살펴보면, 반환값은 당연히 int 형이면 되지만, 매개변수의 경우에는 특정한 룰이 있습니다.

ObjectDataSource의 SelectMethod에 지정된 메서드의 매개변수를 모두 포함하여야 하고, 추가로 마지막에 두 개의 int 형을 가져야 한다는 것인데, 이 규칙을 ObjectDataSource에 대입하면 GetBySubjectCount의 시그니처는 다음과 같게 됩니다.

public int GetBySubjectCount(string text, int startRowIndex, int maximumRows)

시그니처만 알아내면 실제 구현은 무척 간단합니다.

GetBySubject 메서드가 정의된 MemoBiz 클래스에 GetBySubjectCount 메서드를 정의합니다.

image

마찬가지로 단 한 줄의 코드로 구현이 가능합니다.

GetBySubjectCount 메서드를 구현했으니 ObjectDataSource의 SelectCountMethod 속성의 값을 GetBySubjectCount 라고 설정합니다.

StartRowIndexParameterName와 MaximumRowsParameterName 속성의 값은 각각 페이징 메서드에서 가져올 로우의 인덱스와 갯수를 지정하는 매개변수의 이름을 나타내는데, 기본값은 각각 startRowIndex와 maximumRows로 지정이 되어 있습니다.

위에서 구현한 GetBySubjectCount의 매개변수의 이름이 이 기본값과 이미 동일하게 설정되어 있으므로 이 두 속성은 지정하지 않아도 괜찮습니다.

여기까지 작업된 ObjectDataSource의 코드는 다음과 같습니다.

image

ListView 추가

메모의 목록을 표시하기 위해서 ListView 컨트롤을 사용하겠습니다.

MemoList.aspx 페이지에 ListView 컨트롤을 추가하고 아래와 같이 구성합니다.

image

ListView에 대한 설명은 이 포스트의 범위를 넘어 자세한 설명을 할 수는 없지만, ListView는 ASP.NET 3.5에서 가장 강력한 데이터 바인딩 컨트롤입니다.

적어도 MSDN에 있는 ListView의 설명 만은 꼭 익혀두시길 권장합니다.

DataPager의 추가

페이징을 사용하기 위해 DataPager 컨트롤을 추가합니다.

image

페이징을 시연하기 위해 PageSize를 3으로 지정하였습니다.

MemoList.aspx의 완성

여기까지 해서 MemoList.aspx 페이지가 완성되었습니다.

프로젝트를 실행하면 아래와 같은 화면을 볼 수 있습니다.

image

링크를 눌러 보면 검색과 페이징이 동작함을 확인할 수 있습니다.

MemoDetail.aspx의 ObjectDataSource

지금부터는 Midnight Peach 2.0 샘플 애플리케이션, 웹 애플리케이션의 두 번째 페이지인 MemoDetail.aspx를 만들어보도록 하겠습니다.

프로젝트에 MemoDetail.aspx를 추가하고 ObjectDataSource를 추가합니다.

ObjectDataSource를 추가하는 이유는 메모 엔터티의 상세 정보를 보여주기 위해 DetailsView 컨트롤의 사용할 것인데, 이 DetailsView의 데이터 소스로 ObjectDataSource를 사용하기 때문입니다.

먼저 ObjectDataSource를 구성한 후 DetailsView 컨트롤을 추가하도록 하겠습니다.

ObjectDataSource 구성 대화상자나 이용하거나 직접 타이핑하거나 하여 아래와 같이 ObjectDataSource를 구성합니다.

image

이번 경우에는 ObjectDataSource에 지정된 모든 메서드가 MP에서 이미 생성해 둔 것이므로 추가로 비지니스 메서드를 만들 필요가 없습니다.

바로 DetailsView 컨트롤로 넘어 갑시다.

DetailsView 컨트롤

MemoDetail.aspx 페이지에 DetailsView 컨트롤을 추가하고 아래와 같이 설정합니다.

image

대체로 이해하기 무난한 코드인데, 두 개의 이벤트 핸들러에 관해서는 좀 더 설명을 드려야 할 것 같습니다.

먼저 OnItemUpdating 이벤트의 이벤트 핸들러를 다음과 같이 구현합니다.

image

OnItemUpdating 이벤트는 물론 Memo 객체가 변경되기 전에 발생하는데, DetailsViewUpdateEventArgs의 NewValues에는 새로 업데이트 할 값이 저장되어 있습니다.

이때 Memo 객체의 경우에는 두 가지 문제가 발생합니다.

먼저 WrittenAt 속성은 DateTime 형인데, 새로 업데이트할 값으로 전달된 값은 string 형입니다. 따라서 이를 DateTime 형으로 형변환을 하여야 합니다.

또 Body 속성은 null을 허용하지 않으므로, 만일 null이 전달된다면 빈 문자열로 변환하여야 합니다.

마찬가지로 OnItemInserting 이벤트는 Memo 객체가 추가되기 전에 발생합니다.

역시 DetailsViewUpdateEventArgs의 Values에는 추가될 Memo 객체의 값이 넘어옵니다.

여기서 추가될 Memo 객체는 Memo의 기본 생성자로 생성되는데, 그렇다면 그 멤버 필드는 기본값으로 초기화가 됩니다.

즉, Memo 객체라면 WrittenAt은 DateTime형이니까 1년 1월 1일 자정이라는 값을 가지고 string 형인 Subject 등은 null 값을 가지게 됩니다.

하지만 Memo 객체는 DB 스키마와 DBML 파일의 정의에 의해 이러한 값을 지정할 수 없습니다.

따라서 아래와 같이 새로 생성된 Memo 객체의 값을 적당한 값으로 초기화하는 코드가 필요합니다.

 

이렇게 해서 메모패드 웹 애플리케이션을 만들어보았습니다.

:

C# CAPTCHA(자동가입방지용 이미지) 라이브러리

RTFM/C# 2009. 3. 25. 18:02

http://www.codeproject.com/KB/library/captchaimage.aspx

 

C# CAPTCHA 라이브러리를 소개합니다.

SixPack 이라는 라이브러리에 포함된 CaptchImage 클래스를 사용하면 아래와 같은 자동가입방지용 이미지를 쉽게 만들 수 있습니다.

foobar

:

문자열을 64비트 정수로 변환하는 메서드

RTFM/C# 2009. 3. 25. 17:52

http://www.codeproject.com/KB/library/String_To_64bit_Int.aspx

 

닷넷 프레임웍에는 GetHashCode라는 메서드가 있어 문자열을 32비트 정수로 변환할 수 있습니다.

하지만 이렇게 변환된 정수는 유니크한 값이라는 보장을 하지 못합니다.

이에 대한 대안으로 이 아티클에서는 문자열을 64비트 정수로 변환하는 방법을 설명합니다.

물론 64비트 정수라고 해서 유니크함을 보장하지는 않지만, 중복될 확률은 아주 희박해집니다.

아티클 저자의 실험에 의하면, 천만 번을 수행하였을 때, GetHashCode에서는 4,150 개의 중복이 발생한 반면에 GetInt64HashCode에서는 한 개의 중복도 없었다고 합니다.

(아티클의 댓글에 의하면 1억 번을 수행하여도 중복된 값이 없다고 합니다. 또한 참고로 수행에 걸린 시간은 각각 35 ms와 830 ms로 32비트 정수가 월등히 빨랐습니다.)

 

그렇다면 이 메서드가 어떤 경우에 필요할까요?

아티클에도 등장하는 예이지만, 아주 긴 URL을 DB 테이블에 저장하고 이 컬럼에 인덱스를 거는 경우를 생각해봅시다.

두 가지가 문제가 될 수 있습니다.

  1. 인덱스 키의 최대 크기를 초과하는 URL을 저장할 수 없습니다.
  2. 인덱스 키가 커지면 성능이 나빠질 수 밖에 없습니다.

그래서 이에 대한 대안으로 64비트 정수형 컬럼을 추가하고, URL 컬럼이 아닌 이 컬럼에 인덱스를 거는 것입니다.

그렇다면, 특정 URL에 대한 쿼리가 들어오면 이에 대한 64비트 정수값을 얻어서 인덱스 스캔을 할 수가 있을 것입니다.

물론 상황에 따라 취사선택할 문제이긴 하나 진지하게 검토해볼 만한 가치가 있는 기법이라는 생각이 듭니다.

:

토픽 기반의 발행자/구독자 디자인 패턴 구현

RTFM/WCF 2009. 3. 25. 17:29

http://www.codeproject.com/KB/IP/SocketBasedPubSub.aspx

http://www.codeproject.com/KB/IP/PubSubUsingWCF.aspx

 

1

2 

여기서 ‘토픽 기반’ 이란 구독자가 관심 있는 토픽에 대해 구독을 신청하면 발행자가 구독을 신청한 구독자들에게만 데이터를 전송하는 모델을 이야기 합니다.

간단하고 범용적이고 확장성이 풍부한 패턴이라고 하겠습니다.

본문에서는 동일한 애플리케이션을 소켓 버전과 WCF 버전으로 각기 구현을 하고, 각각의 장단에 대해서 설명 합니다.

(메신저 등을 만들 때) 소켓 통신에 대한 대안으로 WCF를 생각하고 있다면 많은 도움이 될 것 같습니다.

:

SQL Server 2008 Management Studio의 새로운 기능

RTFM/SQL 2009. 3. 24. 14:10

http://dotnetslackers.com/articles/sql/SQL-Server-2008-Management-Studio-New-Features.aspx


SQL Server 2008 Management Studio의 새로운 기능 중 주요한 5가지를 소개합니다.

  • 쿼리 편집기에서 인텔리센스 지원
  • 멀티 서버 쿼리
  • 쿼리 편집기에서 영역(#region / #endregion) 지원
  • 향상된 개체 탐색기
  • 활동 모니터링

이 중 일부는 SQL Server 2008 Management Studio Express에서도 동작하는 것을 확인하였습니다.

쿼리 편집기에서 인텔리센스 지원 하나만 놓고 보더라도 SQL Server 2008 Management Studio를 사용해야 할 충분한 이유라는 생각이 듭니다.

: