2011-02-24 2 views
1

나는 수백 개의 클라이언트가 호출하는 WCF 서비스를 디자인하고 있으며 데이터베이스 쿼리에 의해 실행될 클래스에 대한 최상의 아키텍처에 대한 질문이 있습니다. 오늘은 SQL Server에만 액세스하므로 내부적으로 호출하는 정적 클래스가있어서 연결 및 데이터 레이아웃을 만드는 모든 더러운 작업을 수행합니다. 다음은 간단한 예입니다.데이터베이스 도우미 클래스에 대한 C# 디자인 패턴

namespace DBHelper.Utility 
{ 
    public static class SqlDBManager 
    { 
    public static void RunSql(String pSql, DBParamsHelper pDBParams, String pConnStringConfigName) 
    { 
     String sConnectionString = GetConnectionStringFromConfig(pConnStringConfigName); 
     SqlConnection oConn = new SqlConnectionsConnectionString 
     oConn.Open(); 
     try 
     { 
     SqlCommand oCommand = new SqlCommand(pSql, oConn); 
     oCommand.CommandTimeout = 0; 
     if (pDBManagerParams != null) 
     { 
      foreach (SqlParameter sqlParam in pDBManagerParams) 
      { 
      oCommand.Parameters.Add(sqlParam); 
      } 
     } 
     oCommand.ExecuteNonQuery(); 
     } 
     finally 
     { 
     oConn.Close(); 
     } 
    } 
    } 
} 

이제 SQL Server와 Oracle을 모두 실행하기위한 지원을 추가해야합니다. 나의 초기 아이디어는 인터페이스를 선언하고 내 기존의 SqlDBManager을 구현 한 다음 동일한 인터페이스를 구현하는 OracleDBManager을 개발하는 것이 었습니다. 문제는 내 클래스가 정적이며 정적 클래스가 인터페이스를 구현할 수 없다는 것입니다. 헬퍼 클래스를 정적으로 유지하고 싶습니다. 훨씬 실용적이어서 쿼리를 실행할 때마다 새 개체를 만들 필요가 없습니다. 나 또한 클래스 상속을 사용하는 방법을 생각했지만 statis 가상 메서드를 사용할 수는 없으므로 많이 사용하지 않습니다. 나는 싱글 톤 구현을 고려하여 클래스를 생성 할 필요가 없지만 멀티 스레드 액세스에 문제가 발생했습니다.
최상의 디자인 패턴이 될 수 있도록 여러 스레드 시나리오 (매우 중요)에서 성능이 뛰어나고 생산성을 위해 너무 많이 코딩하지 않고 (많은 클래스를 만들 필요가 없음) 두 가지 표준 방법을 모두 사용할 수 있습니다. OracleDBManagerSqlDBManager 클래스? 표준 메서드는 매우 중요합니다. 왜냐하면이 도우미 클래스를 사용하는 코드가 Oracle 또는 SQL Server에 연결되어 있는지 여부를 알기를 원하지 않기 때문입니다.
Entity Framework 4 및 nHibernate와 같은 ORM 솔루션 사용을 고려해 보았지만 성능에 미치는 영향은 너무 컸습니다. 간단한 쿼리를 실행하기 때문에 PL-SQL과 TSQL 간의 쿼리 구문 차이는 중요하지 않습니다.
모든 의견과 아이디어는 높이 평가됩니다. Tks

답변

2

인터페이스가 올바른 방향이지만, 지적했듯이 정적 클래스로 인터페이스를 구현할 수 없습니다. 나는 객체 생성의 번거 로움을 최소화하고자하지만 두 가지 다른 데이터베이스 클래스를 갖기 위해서는 어떤면에서 필요하다고 생각한다.

내가 제안하는 해결책은 다각 면다. 위에 나열된 것을 먼저 유사한 서명이 인터페이스는 다음과 같습니다

SQL-및 오라클 - 특정 버전에서 구현 될 수
public Interface IDbManager { 
    void RunSql(String pSql, DBParamsHelper pDBParams, String pConnStringConfigName) 
} 

, 당신은 이미 그냥 비 정적 위해선, SQL 버전을 사용하고 구현 인터페이스.

이제 아마도 같은 데이터베이스 공장을 시도해보십시오 : 다음

public static class DbFactory { 
    public static IDbManager CreateDb(DbType type) { 
     select (type) { 
      case DbType.Sql: 
       return new SqlDbManager(); 
       break; 
      case DbType.Sql: 
       return new OracleDbManager(); 
       break; 
     } 
    } 
} 

당신은 같은 것을 할 수 있어야한다 :

var db = DbFactory.CreateDb(DbType.Sql); 
db.RunQuery(...); 

이 코드는 안된이다, 그러나 희망 당신은 아이디어를 얻을 . 나는 다른 데이터 저장소에서 데이터를 가져와야하는 프로젝트에서 비슷한 솔루션을 사용합니다. 전략과 공장 패턴은이 과정을 쉽게 해줍니다.

희망 하시겠습니까?

+0

그랜트, 당신을위한 제안. 공장 클래스와 열거 자 (enumerators)와 함께 제가 생각한 바로 그 것입니다. 그냥 개체 생성을 피하기 위해,하지만 정말 확실하지 않은 방법이 있다면 ... Tks! – Pascal

+0

개체 생성을 피할 수있는 유일한 방법은 단일 정적 클래스를 사용하고 DB 개체를 만들 때마다 DB 형식의 스위치를 사용하는 것입니다. 앞서 언급 한 프로젝트에서이 작업을 처음 수행했습니다. 너무 번거 롭습니다! 그런 다음 데이터 액세스를 방금 제시 한 내용으로 변경했습니다. 훨씬 간단하고, 실제로, 그리고 다른 데이터 공급자를위한 전문 수업을 용이하게합니다. –

2

정적 메서드 전용을 만들려면 MS-SQL/Oracle을 지원하는 인터페이스에서 클래스를 래핑하고 해당 인터페이스에서 개인 정적 메서드를 호출하십시오.

예컨대 :

public interface ISqlDbManager 
{ 
    void SaveOrder(Order o); 
    void FindOrderById(int orderId); 
} 

public class SqlServerDbManager : ISqlDbManager 
{ 
    private static void RunSql(String pSql, DBParamsHelper pDBParams, String pConnStringConfigName) 
    { 
     // implement as you did above 
    } 

    public void FindOrderById(int orderId) 
    { 
     // create SQL, call private "RunSql" method. 
    } 
} 

다른 구현 (OracleDbManager)에 대해 같은 일을 할.

소비자는 기본 지속성 메커니즘이 어떻게 작동하는지주의하지 않아야하므로 개인화하는 것이 좋습니다.

또한 단위 테스트가 더 쉬워집니다. 개인 정적 메서드가 메모리 내 목록에 대한 기본 LINQ 작업을 수행하는 "MockDbManager"클래스를 만듭니다.

참고로 은 SQL 명령을 수동으로 생성하는 대신 저장 프로 시저를 사용하는 것이 좋습니다 (). 쿼리 계획 캐싱/최적화에 더 좋습니다.

+0

나는 procs 권고안에 전적으로 동의한다. 그러나 모든 비즈니스 개체에 대해 데이터베이스 코드를 반복해야합니다. – Pascal

+0

@Pascal - correct. 그게 뭐가 잘못 됐니? 객체 당 CRUD procs 집합입니다. 그렇게하면 당신은 그들을 분리시킬 수 있습니다. ATM에는 모든 단일 오브젝트가 사용하는 하나의 메소드가 있습니다. – RPM1984

+0

@ RPM194 이제 당신의 요지를 이해합니다. 그러나 제 수업은 procs/queries를 실제로 실행하기 위해 지루한 것들을 중앙화하는 도우미 클래스입니다. 나는 당신의 의견을 들어 주시고 귀하의 의견을 기다리는 시간을 매우 소중하게 생각합니다. 그러나 그것은 좋은 생각입니다. 그러나 현재 내가 필요로하는 것에 적합하지 않습니다. 하지만 고마워. – Pascal

관련 문제