'Midnight Peach'에 해당되는 글 25건

  1. 2008.10.09 사용자 정의 로직의 추가
  2. 2008.10.09 단위 테스트 코드를 이용한 사용 예제
  3. 2008.10.08 Midnight Peach가 만들어 낸 코드
  4. 2008.10.08 Midnight Peach의 빠른 시작
  5. 2008.10.08 Midnight Peach 소개와 FAQ

사용자 정의 로직의 추가

Midnight Peach 2008. 10. 9. 00:04

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

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

이번에는 좀 더 실용적인 예제를 살펴 보겠습니다.

MP가 생성해 낸 코드는 기본적인 데이터 액세스 레이어입니다. 가장 흔히 쓰이는 CRUD 작업은 지원되지만, 실무에서 요구되는 복잡한 비지니스는 물론 직접 작성하여야 합니다.

여기서는 사용자 정의 로직을 추가하고 이를 MP가 생성한 코드와 통합하는 방법에 대해서 알아 보겠습니다.

 

첫번째 예는 Memo 엔터티에 속성과 메서드를 하나씩 추가해 보겠습니다.

Memopad.Biz 프로젝트에 Entities 라는 폴더를 만들고 Memo 부분 클래스를 아래와 같이 추가합니다.

 

Entities 폴더나 Memo 클래스는 모두 MP가 생성한 Generated 폴더에 있지만, 이 생성된 Memo 클래스를 수정해서는 안됩니다.

왜냐하면 Memo 테이블의 스키마가 변경되거나 하여 다시 코드를 생성하면 기존의 수정 내용이 덮어씌여지기 때문입니다.

따라서 Generated 폴더 바깥에 Memo 클래스의 부분 클래스를 만들고, 커스텀 로직은 이곳에 작성하도록 합니다.

물론 부분 클래스이기 때문에 네임 스페이스는 동일하여야 합니다. (여기서는 Memopad.Biz)

(참고로 Memo와 같은 엔터티 클래스는 세 개의 부분 클래스로 이루어집니다. 첫번째는 LINQ to SQL 디자이너가 생성한 것이고(Memopad.designer.cs), 두번째는 MP가 생성해 낸 것이고(\Generated\Entities\Memo.cs), 마지막은 사용자가 추가한 것입니다. (여기서는 \Entities\Memo.cs))

Memo 클래스에는 작성일(시각을 제외한) 속성과 유효한 상태인지를 검사하는 메서드를 예제로 추가하였습니다.

 

이번에는 Memo의 DTO 객체인 MemoManager에 새로운 쿼리를 추가해 보겠습니다.

조회수가 N 이상인 메모의 제목과 본문을 각각 키와 값으로 하는 SortedDictionary를 반환하는 메서드를 만들겠습니다.

Memopad.Biz 프로젝트에 Managers 라는 폴더를 만들고 MemoManager 부분 클래스를 추가합니다.

 

메서드를 하나 더 추가해 봅시다.

Memo 테이블은 계층적인 구조를 가집니다. 이를 이용하여 자신과 자신의 자손들을 반환하는 메서드를 추가해 봅시다.

이러한 재귀적인 쿼리는 LINQ to SQL로 작성하기 보다는, SQL 서버 2005에 새로 추가된 CTE(Common Table Expression) 구문을 사용하는 것이 더욱 효율적입니다.

따라서 이번에는 저장 프로시져를 이용하도록 하겠습니다.

 

데이터베이스에 아래와 같은 저장 프로시져를 추가합니다.

 

이 프로시져를 실행한 결과는 다음과 같습니다.

exec Memo_GetChildren 1

 

비주얼 스튜디오에서 LINQ to SQL 디자이너를 열고, 서버 탐색기에서 Memo_GetChildren 프로시져를 Memo 클래스로 끌어다 놓습니다.

 

이제 MemoDataContext 클래스에 Memo_GetChildren 이라는 메서드가 생겼습니다.

MemoManager 클래스에 아래와 같이 메서드를 추가합니다.

Memopad.Console 프로젝트에 아래와 같은 코드를 추가하여 결과가 제대로 나오는지 확인해 봅니다.

 

실행한 결과는 다음과 같습니다.

 

이상 MP가 생성해 낸 코드에 사용자 정의 로직을 추가하는 방법에 관해서 알아 보았습니다.

:

단위 테스트 코드를 이용한 사용 예제

Midnight Peach 2008. 10. 9. 00:02

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

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

지금부터는 위에서 생성된 코드를 가지고 실제로 CRUD 작업을 하는 코드를 보도록 합시다.

따로 샘플을 만들 필요 없이 MP 개발 중에 사용한 단위 테스트 코드 조각을 예제로 사용하면 될 것 같습니다.

(이하의 코드들은 비주얼 스튜디오 2008의 테스트 프로젝트를 이용하여 작성한 단위 테스트 코드 입니다.)

먼저 각 테스트가 수행되기 전 항상 DB를 초기화하는 메서드를 만들어 놓고 시작하겠습니다.

ManagerRepository.TruncateAll() 메서드는 Memo 테이블의 모든 데이터를 삭제하고 identity 값을 0으로 설정하는(DBCC CHECKIDENT ('Memo', RESEED, 0)) 저장 프로시저에 대한 래퍼입니다.

Get

public List<T> Get()

public List<T> Get(int startRowIndex, int maximumRows)

public List<T> Get(Expression<Func<T, bool>> where)

public List<T> Get(Expression<Func<T, bool>> where, int startRowIndex, int maximumRows)

public List<T> Get<U>(Expression<Func<T, U>> orderBy, bool ascending)

public List<T> Get<U>(Expression<Func<T, U>> orderBy, bool ascending, int startRowIndex, int maximumRows)

public List<T> Get<U>(Expression<Func<T, bool>> where, Expression<Func<T, U>> orderBy, bool ascending)

public List<T> Get<U>(Expression<Func<T, bool>> where, Expression<Func<T, U>> orderBy, bool ascending, int startRowIndex, int maximumRows)

Get은 엔터티의 컬렉션을 반환하는데 매개 변수로 필터링과 정렬과 페이징을 지정할 수 있습니다.

따라서 Get은 총 2 * 2 * 2 = 8 개의 오버로드를 가지고 있습니다.

하나씩 살펴보면 다음과 같습니다.

GetSingle

public T GetSingle(Expression<Func<T, bool>> where)
public T GetSingle(PK 매개변수)

GetSingle은 조건식에 맞는 한 개의 엔터티를 구합니다.

일반적으로 PK가 조건식으로 지정되며, 조건에 맞는 엔터티가 하나도 없으면 null이 반환되고, 두 개 이상이면 InvalidOperationException이 발생합니다.

조건은 람다식으로 지정하거나 변수로 지정할 수 있습니다.

GetFirst

public T GetFirst()

public T GetFirst(Expression<Func<T, bool>> where)

public T GetFirst<U>(Expression<Func<T, U>> orderBy, bool ascending)

public T GetFirst<U>(Expression<Func<T, bool>> where, Expression<Func<T, U>> orderBy, bool ascending)

조건식에 맞는 엔터티를 지정된 정렬 방법에 따라 정렬했을 때 첫번째 엔터티를 구합니다.

지정된 조건을 만족하는 엔터티가 없으면 null  값이 반환됩니다.

GetLast

public T GetLast()

public T GetLast(Expression<Func<T, bool>> where)

public T GetLast<U>(Expression<Func<T, U>> orderBy, bool ascending)

public T GetLast<U>(Expression<Func<T, bool>> where, Expression<Func<T, U>> orderBy, bool ascending)

첫번째가 아닌 마지막 엔터티를 반환하다는 점을 제외하고는 GetFirst와 동일합니다.

GetCount

public int GetCount()
public int GetCount(int startRowIndex, int maximumRows)
public int GetCount(Expression<Func<T, bool>> where)
public int GetCount(Expression<Func<T, bool>> where, int startRowIndex, int maximumRows)

지정된 조건식에 맞는 엔터티의 갯수를 구합니다.

startRowIndex와 maximumRows  매개변수는 지정되더라도 아무런 동작을 하지 않습니다.

(ObjectDataSource가 요구하는 메서드 시그니처를 맞추기 위해 있습니다.)

Create

public T Create()

public T Create(DateTime defaultDateTime)

엔터티를 생성합니다.

리플렉션을 사요하여 엔터티의 필드 중 string형의 필드는 string.Empty로, DateTime형 필드는 DateTime.Today 혹은 지정된 DateTime 값으로 초기화합니다.

기본값이 설정된 상태로 엔터티를 생성할 때 편리합니다.

Clone

public T Clone(T source)

엔터티를 복사합니다. ColumnAttribute 특성이 지정된 속성만 복사합니다. 주로 Update와 Delete 메서드 내부에서 사용됩니다.

Insert

public virtual void Insert(T entity)

엔터티를 데이터베이스에 삽입합니다.

Identity 컬럼은 삽입 후 자동으로 설정됩니다.

NULL을 허용하지 않는 컬럼에 값이 설정되지 않으면 SqlException 예외가 발생합니다.

Create 메서드로 생성된 엔터티는 기본값이 설정되어 있으므로 (string과 DateTime형) 이러한 문제를 피할 수 있어 편리합니다.

Update

public virtual void Update(T entity)

엔터티를 변경합니다.

Delete

public virtual void Delete(T entity)
public void Delete(PK 매개변수)

엔터티를 삭제합니다.

삭제할 엔터티 객체를 지정하거나 PK 매개변수를 지정할 수 있습니다.

:

Midnight Peach가 만들어 낸 코드

Midnight Peach 2008. 10. 8. 23:54

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

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

이전 포스트인 Midnight Peach의 빠른 시작에 이어 MP가 생성해 낸 코드에 대해서 좀 더 자세히 살펴보겠습니다.

빠른 시작의 서두에서 잠시 말씀드렸지만 MP는 범용 코드 생성 툴입니다.

사용된 패키지에 따라 다양한 코드가 생성되기 때문에, 여기서는 MP의 기본 내장 패키지인 Default 패키지가 Memopad DBML에 대해 생성해 낸 코드를 살펴보도록 하겠습니다.

전체적인 구조는 다음과 같습니다.

(Memo로 시작하는 클래스들은 각 엔터티마다 하나씩 존재하지만, 편의상 Memo 엔터티만 표시하였습니다.)

Entity<T>

Entity<T> 클래스는 모든 엔터티의 추상 제네릭 클래스 입니다.

Tag 라는 object형 속성을 가지고 있어서, 필요에 따라서 어떤 정보든 엔터티에 저장할 수 있는 기능을 제공합니다.

또한 추상 메서드로 Clone을 정의하고 있으므로 모든 엔터티 클래스는 이 메서드를 구현하게 됩니다.

Memo

MP가 아니라 LINQ to SQL이 생성해 낸 엔터티 클래스입니다.

MP는 이 엔터티 클래스에 대한 부분 클래스를 만들고, 이를 Entity<T> 로부터 상속 받는 코드를 추가합니다.

또한 Clone 추상 메서드에 대한 구현도 덧붙입니다.

MemberColumnName MemberColumn

엔터티의 속성 이름을 각각 문자열 상수와 열거형으로 가지고 있는 일종의 도우미(helper) 클래스와 열거형입니다.

EntityManager<T>

모든 DTO(Data Transfer Object) 객체의 추상 제네릭 부모 클래스입니다.

Default 패키지의 거의 모든 로직이 이 곳에 있습니다.

MemoManager

EntityManager<T>를 상속 받은 실제 DTO 객체입니다.

EntityManager 부모 클래스가 제공하지 않는 커스텀 로직은 이 곳에 위치하게 됩니다.

(나중에 다시 설명드리겠지만, 이 파일이 아닌 partial class로 지정된 다른 파일에 코드를 작성합니다. 기본적으로 자동 생성된 파일은 전혀 건드리지 않는 것이 원칙입니다.)

ManagerRepository

모든 DTO 객체(Manager)들의 저장소입니다.

DTO 객체는 new 연산자를 통해 직접 생성될 수도 있지만, ManagerRepository.Memo 와 같은 식으로 싱글톤으로 접근할 수도 있습니다.

또한 DataContext 객체를 생성하는 CreateDataContext 메서드도 가지고 있습니다.

다음 튜토리얼에서는 이 코드들에 대한 사용 예를 단위 테스트와 함께 살펴보겠습니다.

:

Midnight Peach의 빠른 시작

Midnight Peach 2008. 10. 8. 23:48

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

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

간단한 메모장을 만드는 예를 보면서 MP의 사용방법을 살펴 보도록 하겠습니다.

여기서는 데이터 액세스 레이어만 만들겠습니다.

먼저 데이터베이스 스키마를 작성하여야 겠지요.

사용자 / 메모 / 조회 테이블을 만듭니다.

Memo 테이블은 계층적 구조입니다. ParentID 키가 부모 메모에 대한 참조키입니다.

뷰도 하나 만듭시다. 이 뷰의 이름은 ReadingView 입니다.

데이터베이스 스키마를 만들었으니 이제 비주얼 스튜디오가 출동하면 되겠네요.

비주얼 스튜디오에서 새 솔루션과 클래스 라이브러리 프로젝트를 만듭니다. 솔루션의 이름은 MemopadSolution, 프로젝트의 이름은 Memopad.Biz로 지정합니다.

Memopad.Biz 프로젝트에 새 DBML 파일을 추가합니다.

프로젝트에 LINQ to SQL 클래스 항목을 추가하고 이름은 Memopad로 합니다.

서버 탐색기에서 위에서 만든 데이터베이스를 연후, 테이블과 뷰를 화면 가운데로 끌어 옵니다.

데이터베이스 연결 문자열은 설정 파일에 저장이 되는데, 이 때 암호와 같은 중요한 정보도 같이 저장하겠냐고 물어보는 대화상자가 열립니다.

예 혹은 아니오를 선택하고 다음으로 넘어갑니다.

이제 MP를 실행합니다.

MP에서 코드 생성은 3단계의 대화상자를 거치게 됩니다.

첫번째 대화상자에서는 DBML  파일과 패키지 파일을 선택합니다.

DBML 파일은 위에서 만든 Memopad.dbml을 선택하고, 패키지는 내장 패키지인 Default를 선택하고 확인을 누릅니다.

두 번째 대화 상자에서는 코드를 생성할 테이블 혹은 뷰를 선택합니다.

코드 생성 컬럼이 선택되지 않은 테이블 혹은 뷰에 대해서는 코드가 생성되지 않습니다.

기본값은 모든 테이블/뷰에 대해 코드를 생성하는 것입니다.

(위 그리드에서 배경 색상이 연한 노란색이 아닌 셀은 읽기 전용 데이터이며, 코드 생성 컬럼의 헤드 부분을 누르면 전체 선택 / 해제가 토글됩니다.)

확인을 눌러 다음으로 넘어갑니다.

아래와 같은 경고 대화상자가 나타납니다.

Timestamp 형식 컬럼을 이용한 업데이트 동시성 검사가 지정되지 않았기 때문에, 각 컬럼의 UpdateCheck 특성을 "Never"로 설정하여 업데이트 동시성 검사를 하지 않도록 DBML 파일을 수정한다는 의미입니다.

(업데이트 동시성 검사와 LINQ to SQL 및 MP간의 관계에 대해서는 다음 문서에서 자세히 설명하도록 하겠습니다.)

여기서는 "예"를 선택하여 다음으로 넘어갑니다.

마지막 대화상자는 패키지의 옵션을 설정하는 대화상자 입니다.

패키지의 설정은 크게 변수와 템플릿 두 부분으로 나누어 집니다.

각 세부 항목은 패키지에 따라 다를 수 있습니다.

MP의 내장된 기본 패키지인 Default 패키지의 경우에는 두 개의 변수와 다섯 개의 템플릿이 있습니다.

변수인 Namespace와 ConnectionString은 각각 생성될 코드들의 네임 스페이스와 데이터베이스 연결 문자열을 의미합니다.

데이터베이스 연결 문자열의 경우에는 "server=A; database=B; uid=C; pwd=D"와 같이 직접 지정할 수도 있고 위 그림과 같이 설정 파일을 사용하도록 지정할 수도 있습니다.

템플릿의 경우에는 생성될 코드가 저장될 경로를 지정합니다. 나중에 메인 폼에서 "저장" 명령을 통해 생성된 코드를 파일로 저장할 때 폴더를 지정하면 여기에 정의된 상대경로에 따라 각각의 생성된 코드들이 파일로 저장됩니다.

또한 템플릿의 범위가 "table"인 경우에는 자리표시자인 "{0}"를 사용할 수 있습니다. 이 자리표시자는 테이블의 이름으로 치환이 됩니다. 예를 들어 Memo와 Member라는 두 개의 테이블이 있다면, Generated\Entities\{0}.cs 는 각각 Generated\Entities\Memo.cs와 Generated\Entities\Member.cs로 치환이 됩니다.

여기서는 위 그림과 같이 설정을 하고 "확인"을 누릅니다.

이제 코드가 생성되고 MP의 메인 폼이 열립니다.

왼쪽에 있는 트리뷰에서 각 항목을 선택하면 오른쪽의 텍스트 상자에 해당 내용이 표시됩니다.

트리뷰의 구조는 다음과 같습니다.

데이터베이스 범위 템플릿과 테이블(뷰) 범위 템플릿이 순서대로 표시되어 있는데, 이 중에서 템플릿 이름을 누르면 텍스트 박스에 템플릿 자체가 표시됩니다. 반면에 데이터베이스 이름이나 테이브/뷰의 이름을 클릭하면 텍스트 박스에 해당 템플릿에 의해 생성된 코드가 나타납니다.

"저장" 툴바 버튼을 클릭하면 폴더를 선택한 후 생성된 코드를 파일로 저장합니다.

"확인"을 누르면 모든 생성된 코드를 선택된 폴더의 하위에 저장합니다.

이때 저장 경로는 패키지 옵션 중 템플릿의 저장위치에 설정된 값에 의해 결정됩니다.

여기서는 바탕 화면을 선택합니다.

이제 다시 비주얼 스튜디오로 돌아갑니다.

윈도우 탐색기에서 바탕 화면에 있는 Generated 폴더를 선택한 후 비주얼 스튜디오의 솔루션 탐색기의 Memopad.Biz 프로젝트로 끌어옵니다.

패키지 옵션에서 연결 문자열로 "ConfigurationManager.ConnectionStrings[0].ConnectionString"를 지정하였기 때문에 Memopad.Biz 프로젝트에 "System.Configuration" 어셈블리에 대한 참조를 추가합니다.

마지막으로 프로젝트 생성시 추가된 Class1.cs 파일을 삭제하면 Memopad의 기본 데이터 액세스 레이어가 완성되었습니다.

(정확하게는, 우리가 만든 레이어는 비지니스 로직 레이어이며, 데이터 액세스 레이오는 이 비지니스 로직 레이어 내부에 포함되어 있습니다. 아키텍쳐에 관해서는 이후에 좀 더 자세히 설명드리도록 하겠습니다.)

이제 Memopad의 프리젠테이션 레이어를 만들어 봅시다.

여기서는 간단힌 콘솔 응용프로그램을 만들겠습니다.

솔루션에서 새 콘솔 응용프로그램을 추가하고 이름은 Memopad.Console라고 합니다.

콘솔 응용프로그램에서 새 항목 추가로 응용프로그램 구성 파일을 추가하고 아래와 같이 연결문자열을 설정합니다.

주의할 점은, name 특성은 중복만 아니라면 아무 값이나 지정해도 무방하지만, 위에서 ConfigurationManager.ConnectionStrings[0].ConnectionString로 지정되었기 때문에, <clear />가 먼저 나와서 첫번째 연결 문자열로 만들어줘야 한다는 것입니다.

Memopad.Console의 Program.cs 파일에 아래와 같은 테스트 코드를 작성하고 결과를 확인해봅니다.

콘솔에 "0" 이 출력되면 정상입니다.

여기까지 해서 MP의 사용 방법에 대해 간략하게 살펴보았습니다.

다음 문서에서는 MP가 만들어낸 코드에 대해서 좀 더 자세히 살펴보도록 하겠습니다.

:

Midnight Peach 소개와 FAQ

Midnight Peach 2008. 10. 8. 23:45

[주의]
이 글은 MP의 현재 버전 (3.X)에 맞지 않습니다.
 
단순 참고용으로만 활용하십시오 

MP(Midnight Peach)는 LINQ to SQL을 기반으로 하는 범용 코드 생성 툴입니다.

DBML 파일과 템플릿(내장 템플릿 혹은 사용자 정의 템플릿)을 결합하여 다양한 코드를 생성할 수 있습니다.

 

설치

http://snssoft.net/MidnightPeach/publish.htm

 

소스

다운로드

 

FAQ

누가 어떤 용도로 사용하는 툴입니까?

개발자가 LINQ to SQL을 기반으로 하여 데이테 액세스 레이어 코드를 만들어 내는 툴입니다.

사용 환경은 어떻습니까?

MP 자체를 실행하기 위한 환경은 .NET Framework 3.5 SP1만 설치되어 있으면 됩니다.

MP가 생성해낸 코드를 실행하기 위한 환경은 LINQ to SQL의 환경과 동일합니다.

지원하는 데이터베이스는 무엇입니까?

LINQ to SQL이 지원하는 데이터베이스를 지원합니다. 즉 SQL 서버 2000 이상을 지원합니다.

지원하는 언어는 무엇입니까?

내장 패키지인 Default는 C# 3.0 코드를 생성하지만, 패키지의 정의에 따라 다른 닷넷 언어용 코드도 생성할 수 있습니다.

MP 자체의 UI는 영어로 되어 있지만, 한국어 지역화 버전도 같이 제공됩니다.

패키지란 무엇입니까?

패키지는 여러 개의 템플릿과 한 개의 템플릿 정의 파일로 이루어진 코드 생성 단위입니다.

템플릿은 MPML에 따라 작성된 매크로 파일입니다. MP는 이 매크로를 DBML 파일에 포함된 클래스로 치환하여 코드를 생성해 냅니다.

MPML 이란 무엇입니까?

MPML(Midnight Peach Macro Language)는 MP에서 사용하기 위해 만든 매크로 언어입니다.

MP에는 이에 대한 파서와 처리기가 포함되어 있습니다.

MPML에 대한 문법(EBNF)은 이 포스트에서 볼 수 있습니다

기술 지원은 어떻게 합니까?

MP의 공식 커뮤니티인  제작자의 블로그에서 지원합니다.

어떠한 라이센스를 따릅니까?

라이센스에 관해서는 좀 더 조사를 해 보고 결정을 해야겠으나 특별한 제한을 두고 싶지는 않습니다.

현재로서는 MP를 이용해서 나쁜짓만 하지 않으면 자유롭게 사용하셔도 좋습니다.

 MP를 사용하다 입게 된 손해에 대해서는 누가 책임집니까?

MP는 사용자에게 알리지 않았거나 예상하지 못한 어떠한 작업도 하지 않습니다.

따라서 만일 사용자의 부주의에 의한 손해가 발생한다면 전적으로 사용자가 책임을 져야 합니다.

 개발자에게 메일 보내도 됩니까?

웰컴이지요. 메일 주소는 kimgwajang@hotmail.com 입니다.

: