데이터베이스 액세스를 어떻게 캡슐화해야합니까?


10

데이터베이스 액세스를 관리하는 데 사용되는 좋은 클래스 구조의 예는 무엇입니까? 나는 클래스 캡슐화의 팬이며 데이터베이스 작업을 수행하지 않는 컨테이너 (예 : 자동차)를 선호합니다.

또한 향후 데이터베이스 캐시와 같은 것을 쉽게 드롭 할 수있는 기능을 원합니다.

컨테이너 클래스의 패턴을 가져와 단일 싱글 톤 클래스에서 수행하는 유효성 검사 및 데이터베이스 액세스를위한 getter 및 setter로 완성되는 경우가 많습니다. 말하자면, 이것은 종종 둘 사이에 혼합되어 상당히 혼란스러워집니다.

내 질문을 이해하기 어려운 경우 죄송합니다. 나는 데이터베이스에 관한 용어를 절대적으로 확신하지 못한다. 필요한 경우 설명을 요청하십시오.


ORM을 사용하여 클래스를 데이터베이스 (예 : Wt :: Dbo) 에 연결하는 것을 고려 했습니까 ?
user52875

답변:


11

데이터 액세스를 캡슐화하기 위해 리포지토리 패턴 을 선호합니다 . 간단히 말해 리포지토리는 특정 개체에 필요한 모든 데이터를로드합니다. 예와 같이 Car 객체가 있다고 가정하십시오. 그러나 자동차, 제조사, 모델, 연도, 소유자, 기능 (CD 플레이어, 4wd 등)에 대한 모든 속성은 데이터베이스 전체의 다양한 테이블에 저장됩니다. 저장소는 데이터로드 및 저장 방법을 결정합니다. 여러 개의 작은 쿼리가 필요한 경우에는 괜찮지 만 리포지토리 패턴 만 알아야합니다. 저장소를 호출하는 서비스 계층은 호출 할 저장소 만 알면됩니다.

그런 다음 작업 단위 패턴 과 결합 될 수 있습니다 . 따라서 귀하의 예에서 서비스 계층은 자동차 엔터티를로드해야한다고 말하고 일종의 고유 식별자를 가지며 해당 식별자를 저장소로 보냅니다. 저장소는 자동차 엔티티를 반환합니다. 일부 다른 코드는 자동차 엔터티를 조작하고 해당 엔터티를 다시 리포지토리로 보내 저장할 수 있습니다.

실제로 모든 것을 처리하려는 경우 리포지토리 계층은 ICarRepository와 같은 인터페이스 만 노출합니다. 저장소에는 서비스 계층이 ICarRepository 인터페이스를 얻는 데 사용할 팩토리 가 포함 됩니다. 모든 데이터베이스 액세스는 인터페이스 뒤에 숨겨져 단위 테스트가 훨씬 쉬워집니다.


OP가 c ++ 태그를 의미하지 않는 한 c ++에 존재하지 않는 인터페이스에 대한 마지막 비트를 제외하고는 모두 훌륭합니다. QT와 함께 사용하려는 C ++에서 리포지토리 패턴 구현이 궁금합니다. 나는 아무것도 사용할 수있는 온라인 = [거기에 놀라 울뿐입니다
johnildergleidisson

6

전략 패턴 을 사용하여 데이터 액세스를 캡슐화했습니다. 이 패턴을 사용하면 공통 인터페이스 뒤에 사용중인 스토리지 유형을 숨길 수 있습니다. 인터페이스에서 스토리지 유형 (파일, 데이터베이스, 웹)을 무시하고 데이터 액세스 방법을 정의하십시오. 그런 다음 현재 스토리지 선택을 위해 전략 인터페이스를 구현하는 클래스에서 데이터 액세스 세부 사항을 구현하십시오. 이렇게하면 응용 프로그램이 사용중인 데이터 소스를 신경 쓰지 않습니다.

현재 데이터 스토리지 전략 인스턴스를 사용하여 데이터 액세스와 비즈니스 로직을 혼합하는 대신 더 많은 애플리케이션 별 세부 정보를 정의하는 서비스 계층을 구축 할 수도 있습니다.


그렇다면 각 유형에 대한 액세스 클래스를 추가하거나 모두에 대해 하나의 큰 클래스를 추가 하시겠습니까?
Will03uk

개인적으로 나는 야생에서 서버 / 응용 프로그램으로 들어오는 모든 데이터에 대해 명시 적 캐스팅을 채택하는 것을 고려할 것입니다.
user827992

+1이 패턴의 모양이 마음에 들지만 (프로젝트 규모에 따라) 데이터베이스에 대해 각 알고리즘을 개별적으로 관리하는 것이 어려울 것입니다. 다른 응용 프로그램에서도 확실히 사용할 것입니다. 람다는 이것을 잘 보완해야합니다.
Will03uk

1

데이터베이스 팩토리 패턴의 예입니다.

using System.Reflection;
using System.Configuration;

public sealed class DatabaseFactory
{
    public static DatabaseFactorySectionHandler sectionHandler = (DatabaseFactorySectionHandler)ConfigurationManager.GetSection("DatabaseFactoryConfiguration");

    private DatabaseFactory() { }

    public static Database CreateDatabase()
    {
        // Verify a DatabaseFactoryConfiguration line exists in the web.config.
        if (sectionHandler.Name.Length == 0)
        {
            throw new Exception("Database name not defined in DatabaseFactoryConfiguration section of web.config.");
        }

        try
        {
            // Find the class
            Type database = Type.GetType(sectionHandler.Name);

            // Get it's constructor
            ConstructorInfo constructor = database.GetConstructor(new Type[] { });

            // Invoke it's constructor, which returns an instance.
            Database createdObject = (Database)constructor.Invoke(null);

            // Initialize the connection string property for the database.
            createdObject.connectionString = sectionHandler.ConnectionString;

            // Pass back the instance as a Database
            return createdObject;
        }
        catch (Exception excep)
        {
            throw new Exception("Error instantiating database " + sectionHandler.Name + ". " + excep.Message);
        }
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.