データベースアクセスをカプセル化するにはどうすればよいですか?


10

データベースアクセスの管理に使用される適切なクラス構造の例は何ですか?私はクラスカプセル化のファンであり、データベースタスクを実行しないようにコンテナ(車など)を好みます。

また、将来的にはデータベースキャッシュなどを簡単にドロップできる機能も必要です。

私はしばしば、単一のシングルトンクラスによって実行される検証とデータベースアクセスのためのゲッターとセッターを備えたコンテナークラスのパターンを採用しています。そうは言っても、これはしばしば2つの間で混合され、かなり混乱します。

私の質問が理解しにくい場合は申し訳ありません。データベースに関する条件については、はっきりとはわかりません。必要に応じて、遠慮なく説明を求めてください。


ORMを使用してクラスをデータベース(Wt :: Dboなど)にリンクすることを検討しましたか?
user52875 2012

回答:


11

私はデータアクセスをカプセル化するためにリポジトリパターンを好みます。簡単に言えば、リポジトリは特定のオブジェクトに必要なすべてのデータをロードする責任があります。例のように、Carオブジェクトがあるとします。ただし、車、メーカー、モデル、年式、所有者、機能(CDプレーヤー、4WDなど)のすべての属性は、データベース全体のさまざまなテーブルに格納されます。リポジトリは、データをロードして保存する方法を決定します。複数の小さなクエリが必要な場合は問題ありませんが、それを知る必要があるのはリポジトリパターンのみです。リポジトリを呼び出すサービス層は、呼び出すリポジトリを知る必要があるだけです。

次に、これを作業単位パターンと組み合わせることができます。したがって、あなたの例では、サービス層は車のエンティティをロードする必要があると言って、ある種の一意の識別子を持ち、その識別子をリポジトリに送信します。リポジトリは、carエンティティを返します。他のいくつかのコードは、carエンティティを操作し、そのエンティティをリポジトリに送信して保存できるようにします。

本当にすべてを実行したい場合、リポジトリ層はICarRepositoryなどのインターフェースのみを公開します。リポジトリには、サービス層がICarRepositoryインターフェイスを取得するために使用するファクトリが含まれます。すべてのデータベースアクセスはインターフェースの背後に隠されるため、ユニットテストがはるかに簡単になります。


(OPがc ++にタグを付けることを意味していなかった場合を除いて)c ++には存在しないインターフェースについての最後のビットを除いてすべて素晴らしい。QTでそれを使用したいので、C ++でのリポジトリパターンの実装を見たいと思っています。オンラインで使用できるものが何もないことに驚きます= [
johnildergleidisson

6

戦略パターンを使用してデータアクセスをカプセル化しました。このパターンにより、使用しているストレージのタイプを共通のインターフェースの背後に隠すことができます。インターフェースで、ストレージのタイプ(ファイル、データベース、Web)を無視してデータアクセスメソッドを定義します。次に、現在のストレージの選択について、戦略インターフェースを実現するクラスで、データアクセスの詳細を実装します。このようにして、アプリケーションは使用しているデータソースを気にしません。

データアクセスとビジネスロジックを混在させる代わりに、現在のデータストレージ戦略インスタンスを使用して、アプリケーション固有の詳細をさらに定義するサービスレイヤーを構築することもできます。


それでは、タイプごとに1つのアクセスクラスを追加するか、すべてのクラスを1つの大きなクラスに追加しますか?
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.