5

ここでは非常に一般的な状況があります。そして、何年もの間、私がやっていることは業界標準によって正しいかどうかわかりませんでした.データベースに接続するアプリケーションを考えてみてください。起動時またはアプリケーションの起動時にデータベースが参照されます。

その接続文字列をアプリのスコープ内のどこかに保存する必要があります。私が見た最も一般的な方法は、接続文字列を保存するための get/set メソッドを持つモジュールまたはグローバル クラスです。もう 1 つの方法は、Singleton を使用することです。どちらのオプションでも、DAL は必要に応じて GetConnectionString メソッドを介して接続文字列にアクセスできます。

これを行うより良い方法はありますか?

更新:私は構成ファイルを持っていません。たとえ持っていたとしても、アプリケーションインスタンスの存続期間中に接続文字列を一度読み取る必要があります。「任意のクラスに注入する」部分について詳しく説明できますか

4

6 に答える 6

8

一般的なグローバル状態では、それがグローバル クラスであろうとシングルトンであろうと、可能な限り避ける必要があります。

理想的な解決策は、アプリケーションが構成から接続文字列をロードし、それを必要とするクラスに注入することです。アプリケーションのサイズによっては、UnityCastle WindsorなどのIoCコンテナーが役立ちますが、ソリューションの必須部分ではないことは確かです。

それがオプションではなく、(既存のコードベースなどの理由で) グローバルな状態を維持することに行き詰まっている場合、提案した 2 つのアプローチに大きな違いがあることを私は知りません。

更新:明確にするために、今のところ IoC コンテナーに関するすべてのことを忘れてください。「注入」は、「パラメーターとして渡す」(クラスのコンストラクター、またはプロパティを介して、またはその他) と言う手の込んだ方法です。

データ アクセス クラスが (ある種のグローバルまたはシングルトンから) 接続文字列を要求するのではなく、コンストラクタまたはプロパティを介して渡されます。

更新 #2:このアプローチが何を伴うのかについて、まだ誤解があると思います。

基本的には、データ アクセス クラスが次のように見えるかどうかにかかっています。

public class DataAccessClass
{
    public DataAccessClass()
    {
        _connString = SomeStaticThing.GetConnectionString();
    }
}

また

public class DataAccessClass
{
    public DataAccessClass(string connString)
    {
        _connString = connString;
    }
}

これらの 記事(実際、そのブログの記事の多く) では、なぜ後者が前者よりも優れているかについて、多くの理由が詳しく説明されています (特に、前者は単体テストがほとんど不可能だからです)。

はい、どこかで、最初に接続文字列を取得する責任を負う静的担当者が必要になりますが、要点は、静的メソッドへの依存関係がその 1 つの場所に限定されていることです (これはおそらくあなたのコードベース全体に散りばめられるのではなく、アプリケーションをブートストラップするプロセスのメイン メソッド)。

于 2009-02-02T17:31:09.723 に答える
5

このような単純な問題に対する非常に多くの創造的な解決策を見るのは素晴らしいことです;-)

OPの質問からの顕著な事実:

  1. connect-stringはコマンドラインで渡されます
  2. 他の多くのコンポーネントは、接続文字列を使用する必要がある場合があります

したがって、静的要素の使用を回避する方法はありません。それがグローバル変数(.NETで実行するのは難しい、実際には、クラスを囲むことなし)であるか、静的クラスであるか、シングルトンであるかは、実際には重要ではありません。最短経路ソリューションは、コマンドラインを処理したProgramクラスによって初期化された静的クラスになります。

他のすべてのソリューションでは、渡された接続文字列への静的アクセスが必要ですが、これは1つ以上の間接層の背後に隠れている可能性があります。

基本的なソリューションをもっと凝ったものでドレスアップしたくないと言っているわけではありませんが、それは必要ではなく、説明されているように接続文字列の基本的に静的/グローバルな性質を排除するものではありません。

于 2009-02-02T18:38:31.680 に答える
4

保存しているのが文字列だけの場合 (おそらく、他のグローバル アプリケーション設定の束と一緒に)、すべてを保持するために、一連のプロパティを持つ静的クラスを使用します。シングルトンはより多くのコードとメンテナンス作業ですが、プロパティ クラスは何もしないため、この場合は不必要な作業です。物を握るだけ。

于 2009-02-02T17:31:42.517 に答える
2

確かに方法はあります。まず、依存性注入や同様の手法について理解を深め、サービス層について読んでください。それがここで必要なことだからです。

サービス層に関する限り、ある種の構成サービスが必要です。これは、アプリケーションの一部が構成情報 (接続文字列、URI など) を照会するモジュールになります。

interface IConfigurationService
    string ConnectionString
    bool IntegratedSecurity
    bool EncryptProfiles

システムにのインスタンスが 1 つしかないことは非常に簡単ですがIConfigurationService、これはシングルトン パターンではなく、選択した DI コンテナーで実現されます。

次に、すべての DAL サービスが への参照を取得しますIConfigurationService

class FooDal : IFooDal
    IConfigurationService ConfigurationService

IConfigurationService.ConnectionString接続文字列を取得するために使用できるようになりました。

于 2009-02-02T17:33:52.807 に答える
1

場合によります。

シングルトンは次のことに注意してください。

  • クラスのインスタンスが 1 つだけ存在することを強制し、
  • グローバルアクセスを提供

グローバルはグローバル アクセスのみを提供しますが、インスタンス化の数については保証しません。

もちろん、最後のオプションは、ローカル変数を使用することです。つまり、構成情報をパラメーターとしてコンストラクターまたは必要な場所に渡します。

最初の 2 つのどちらかを選択するのは、やや簡単です。クラスのインスタンスが 2 つ存在すると大変なことになるでしょうか? おそらくそうではないと思います。アプリの 1 つの特定のコンポーネントに個別のオプションを提供するため、または単体テストを初期化するために、独自の構成クラスをインスタンス化することが必要な場合があります。

インスタンスが 1 つだけ存在することを保証する必要があるケースはほとんどありません。このため、シングルトンよりもグローバルの方が適している場合があります。

ローカルかグローバルかの選択はよりトリッキーです。一般に、グローバルな可変状態は避けるのが最善です。不変状態はそれほど問題ではなく、グローバルな可変状態と同じ同期/同時実行/スケーラビリティの問題につながることはありません。

しかし、多くの場合、それを必要とするコンポーネントに渡すローカル変数として保持する方が望ましい場合があります。これは、DB アクセスが必要なオブジェクトのコンストラクターに渡すだけで手動で行うことができます。または、IoC コンテナーを使用してある程度自動化することもできます。

ただし、いずれにせよ、グローバルでない場合、コードはより汎用的になり、移植性が高くなります。コードが機能するために存在しなければならないクラスやグローバル データへの隠れた依存関係がある場合、他のプロジェクトで簡単に使用できなかったり、コードベース全体をリファクタリングしすぎたりする場合があります。

また、単体テストも難しくなります。これは、理想的にはテストから除外したい外部データが存在しない限り、コードをコンパイルすることさえできないためです。

于 2009-02-02T17:35:11.480 に答える
0

@Antonが言ったように、次のようなものを公開するインターフェースが必要です

interface IConfigurationService
    string ConnectionString

次に、クラスのいずれかが接続文字列を必要とするたびに、有効な文字列を含む構築時に IConfigurationService の実装を提供します。アプリの起動時 (おそらくデータベース アドレスを取得するとき) に実装を作成し、それを必要とするクラスに渡すための有効な場所を見つける必要があります。

シングルトンやグローバルに比べて大変な作業に思えるかもしれませんが、これによりコード内のカップリングが低下するため、再利用性が向上し、単体テストが容易になります。グローバルが (ほとんどの場合) 悪であると自分自身に納得させれば、非常に簡単です :)

前に述べたように、それを行うためのフレームワークを提供する IoC コンテナがありますが、あなたのケースではやり過ぎかもしれません。加えて、「魔法の箱」に作業を任せる前に自分でパターンを使用するのは良いことです。

于 2009-02-02T18:11:39.050 に答える