0

さて、ここで私が直面している問題があります。

アプリケーションに、データベース接続を必要とするメソッドを持つクラスがいくつかあります。クラスを設計する 2 つの異なる方法の間で迷っています。どちらも依存性注入を中心にしています。

  1. メソッド呼び出しの前に呼び出し元によって設定される接続のプロパティを提供します。これにはいくつかの欠点があります。

    • 接続プロパティに依存するすべてのメソッドは、そのプロパティを検証して、それがnullではないこと、開いていること、および操作が台無しになる場合はトランザクションに関与していないことを確認する必要があります。

    • 接続プロパティが予期せず閉じられた場合、すべてのメソッドは (1.) 例外をスローするか、(2.) 強制的に開く必要があります。必要な堅牢性のレベルに応じて、どちらのケースも適切です。(これはメソッドに渡される接続とは異なることに注意してください。接続への参照は、メソッド呼び出しの存続期間だけではなく、オブジェクトの存続期間にわたって存在します。その結果、接続のボラティリティが高くなるように見えます。私に。)

    • プロパティを提供することは、(とにかく、私には)対応するプロパティConnectionを求めて叫ぶようです。Transactionこれにより、トランザクションがいつ使用され、いつ使用されないかを明確にする必要があるため、ドキュメントに追加のオーバーヘッドが生じます。

    一方、Microsoft は、セット アンド インボーク パラダイム全体を支持しているようです。

  2. 接続を引数としてメソッドに渡す必要があります。これには、いくつかの利点と欠点があります。

    • パラメータリストは当然大きくなります。これは、主にコールの時点で、私にとって面倒です。

    • 接続 (およびトランザクション) は使用前に検証する必要がありますが、それへの参照はメソッド呼び出しの間のみ存在します。

    • ただし、要点は非常に明確です。接続を提供する必要があること、およびメソッドが背後で自動的に接続を作成しないことは明らかです。

    • メソッドがトランザクションを必要としない場合 (たとえば、データベースからデータを取得するだけのメソッド)、トランザクションは必要ありません。メソッド シグネチャによる明確さの欠如はありません。

    • メソッドがトランザクションを必要とする場合は、メソッド シグネチャにより非常に明確です。繰り返しますが、明確さの欠如はありません。

    • Connectionクラスはまたはプロパティを公開しないため、Transaction呼び出し元がそれらを介してプロパティやメソッドにドリルダウンしようとする可能性はなく、デメテルの法則が適用されます。

私は知っています、それはたくさんあります。しかし一方では、Microsoft の方法があります。プロパティを提供し、呼び出し元にプロパティを設定させてから、メソッドを呼び出します。そうすれば、複雑なコンストラクターやファクトリー メソッドなどを作成する必要がなくなります。また、多くの引数を持つメソッドは避けてください。

次に、オブジェクトでこれら 2 つのプロパティを公開すると、消費者がこれらのプロパティを悪用するのを助長する傾向があるという単純な事実があります。(私が責任を負っているわけではありませんが、それでもです。) しかし、私はただ、くだらないコードを書きたくないだけです。

あなたが私の立場だったら、どうしますか?

4

2 に答える 2

1

考慮すべき 3 番目のパターンを次に示します。

  • 接続へのアクセスを提供する ConnectionScope というクラスを作成します。
  • いつでもどのクラスでも、ConnectionScope を作成できます
  • ConnectionScope には Connection というプロパティがあり、常に有効な接続を返します。
  • 任意の (およびすべての) ConnectionScope は、同じ基になる接続オブジェクトへのアクセスを提供します (一部のスコープ内、おそらく同じスレッドまたはプロセス内)。

その後、必要に応じてその接続プロパティを自由に実装できます。クラスには、設定する必要のあるプロパティがなく、接続がパラメーターでもなく、接続の開閉について心配する必要もありません。

詳細:

  • C# では、ConnectionScope が IDisposable を実装することをお勧めします。そうすれば、クラスは「using ( var scope = new ConnectionScope() )」のようなコードを記述でき、その後、ConnectionScope は、接続が破棄されたときに (適切な場合) 接続を解放できます。
  • スレッド (またはプロセス) ごとに 1 つの接続に制限できる場合は、ConnectionScope の [thread] 静的変数に接続文字列を簡単に設定できます。
  • 次に、参照カウントを使用して、単一の接続が既に開いているときに再利用され、誰も使用していないときに接続が解放されるようにすることができます

更新: 以下は、簡略化されたサンプル コードです。

public class ConnectionScope : IDisposable
{
   private static Connection m_Connection;
   private static int m_ReferenceCount;

   public Connection Connection
   {
      get
      {
          return m_Connection;
      }
   }

   public ConnectionScope()
   {
      if ( m_Connection == null )
      {
          m_Connection = OpenConnection();
      }
      m_ReferenceCount++;
   }

   public void Dispose()
   {
      m_ReferenceCount--;
      if ( m_ReferenceCount == 0 )
      {
         m_Connection.Dispose();
         m_Connection = null;
      }
   }
}

クラスの 1 つ (任意の) がそれを使用する方法のサンプル コード:

using ( var scope = new ConnectionScope() )
{
   scope.Connection.ExecuteCommand( ... )
}
于 2009-07-21T02:11:23.923 に答える
0

私は後者の方法を好みます。あなたのクラスはデータベース接続を永続層への導管として使用しているようです。データベース接続で呼び出し元を渡すと、これが事実であることが明確になります。接続/トランザクションがオブジェクトのプロパティとして表された場合、物事はそれほど明確ではなく、所有権と存続期間の問題がすべて明らかになります。最初から避けたほうがいいです。

于 2009-07-21T02:10:31.473 に答える