2016-07-14 3 views
0

내 응용 프로그램에 IDataItem을 구현하는 유형 집합이 있습니다. 그것들은 모두 데이터베이스 행을 나타내는 단순한 "DTO"유형입니다. 인스턴스는 데이터베이스에 대해 SQL 선택 쿼리를 실행하여 PetaPoco (마이크로 ORM)를 사용하여 만들어집니다. SQL 선택 쿼리는 유형에 따라 다르며 애플리케이션 버전 번호에 따라 달라집니다 (유형 X가 Y라는 속성을 가지고 있지만 애플리케이션 버전 N 이전에는 DB에 해당 열이 없다고 가정합니다.이 경우 쿼리는 기본값을 반환합니다) Y를위한).IDataItem을 구현하는 각 유형에는 연관된 문자열 (SQL select qry)이 있어야하지만 인스턴스화되기 전에 액세스해야합니다.

응용 프로그램의 특성상 이러한 유형이 많고 앞으로 그 수가 증가 할 것입니다. 데이터 액세스 레이어에서 제네릭을 사용하여 (i) 코드 양을 최소화하고 (ii) 향후 개발자가 유형을 디자인 할 때 필요한 SQL 쿼리를 설계하도록해야합니다.

  • 는 타입 매개 변수 T를 가지고 : IDataItem
  • 는 T
  • 의 IEnumerable을
  • 을 반환과 관련된 SQL 선택 쿼리 결과가 나왔다

    그래서, 데이터 액세스 계층에서 내가 원하는 방법입니다 T

  • PetaPoco를 사용하여 DB에 대한 쿼리를 실행하여 T 의 목록을 만듭니다 (그보다 조금 더 복잡합니다 - 동적 where 절이 있지만 단순하게 유지하기 위해 남겨 둡니다)

내 도전 과제는 - T의 인스턴스가 생성되기 전에 형식 매개 변수 T에 대한 SQL 쿼리를 검색하는 방법입니다. 이상적으로는 IDataItem에 메소드를 추가합니다. string SqlSelectFrom (int appVersion)하지만 인터페이스를 정적 ​​멤버가 필요로하는 경우 인스턴스를 호출해야합니다. 내가 지금이 가장 좋은이 같은 데이터 액세스 계층 내부 기능입니다 (그러나 이것은 정말 SQL 쿼리를 구현하는 미래 유형의 개발자를 강제로 내 요구 사항을 충족하지 않음) :

private string GetSqlSelectFrom<T>(int appVersion) where T : IDataItem 
    { 
     if (typeof(T) == typeof(ProductDto)) 
      return "select ProductId, ProductCode from Product"; 

     if (typeof(T) == typeof(ColourDto)) 
      return "select ColourId, ColourCode from Colour"; 

     etc 

     throw new Exception("No SQL defined!"); 
    } 

이 더 나은가요 이 일을 성취하기위한 패턴?

+0

나는 두 가지 방법을 생각할 수있다 : (1) DTO 유형 에 대한 속성 사용 (2) DTO 유형 –

+0

에 대한 레지스트리 종류 사용 속성은 응용 프로그램 버전에 따라 다를 수 있습니다. 레지스트리 plz에 대해 더 자세히 설명해주십시오. – Laurence

답변

1

한 가지 방법은 DTO 유형 레지스트리의 종류를 사용하고 있습니다 : 어딘가에 응용 프로그램 시작 코드에서

public static class DtoRegistry 
{ 
    private static readonly Dictionary<Tuple<Type, int>, string> _sqlSelectByType = 
     new Dictionary<Tuple<Type, int>, string>(); 

    public static void RegisterDto<T>(int appVersion, string sqlSelect) where T : IDataItem 
    { 
     var key = new Tuple<Type, int>(typeof(T), appVersion); 
     _sqlSelectByType[key] = sqlSelect; 
    } 

    public static string GetSqlSelectFrom<T>(int appVersion) where T : IDataItem 
    { 
     var key = new Tuple<Type, int>(typeof(T), appVersion); 
     return _sqlSelectByType[key]; 
    } 
} 

및 모든 DTO 유형을 등록해야합니다 :

DtoRegistry.RegisterDto<ProductDto>(appVersion: 1, sqlSelect: "SELECT * FROM Products"); 
DtoRegistry.RegisterDto<ProductDto>(appVersion: 2, sqlSelect: "SELECT * FROM ProductsV2"); 

DtoRegistry.RegisterDto<ColourDto>(appVersion: 1, sqlSelect: "SELECT * FROM Colours"); 
DtoRegistry.RegisterDto<ColourDto>(appVersion: 2, sqlSelect: "SELECT * FROM ColoursV2"); 

하나주의를 레지스트리로 스레드 안전성입니다. 단일 스레드에서 응용 프로그램 초기화를 실행하고 레지스트리를 채우고 초기화가 완료되면 레지스트리를 변경하지 않을 것입니다. 그런 다음 응용 프로그램을 실행하는 동안 여러 스레드가 동시에 GetSqlSelectFrom을 안전하게 호출 할 수 있습니다.

+0

유망 하겠지만 SQL 쿼리는 상수가 아닙니다. 앱 버전의 기능입니다. – Laurence

+0

아, 좋아. 나는 대답을 수정하고있다. –

+0

완료 - 이제 앱당 등록 및 조회 작업 –