6

別の開発者が作成したプロジェクトで作業する必要があります。MS-Access を db として、いくつかの OleDbConnections を使用した、Visual-Basic コードを含むプロジェクト Win-Form。バグがあります。データベースで最大接続数に達したために、アプリケーションが OleDbConnection を開けないことがあります。接続を使用する最良の方法は次のとおりです。

Using cn As New OleDbConnction(s)
  ...
  cn.Close()
End Using

しかし、プロジェクトにはデータベースを操作する多くのクラスがあり、これらのクラスの多くには、異なる時間に開いたり閉じたりする「フレンド」可視性を持つ OleDbConnections があります。このため、すべての OleDbConnections を Using コンストラクトに入れることは不可能であり、これらの OleDbConnection の 1 つを閉じる操作を "忘れる" 操作を見つけるのは非常に困難です。

可能な解決策は、一意のパブリック OleDbConnection を 1 つだけ使用し、それを開く前に、まだ開いていないかどうかを確認することです。しかし、それは非常に悪い習慣だと誰かが私に言いました。彼はパフォーマンスについて私にこう言ったのだと思いますが、正確にはわかりません。1 つの一意のパブリック OleDbConnection が非推奨になった理由を教えてください。私にとって、私の問題に対する「簡単な」解決策はありますか?ありがとう、ピレッジ

4

2 に答える 2

6

あなたの説明から、あなたの問題につながる可能性のある問題がいくつかあります。

  • ネストされた接続:
    相互に複数の接続を開きます
  • 接続のオープン/リリースが速すぎる:
    David-W-Fenton が言及したように、アクセスを使用すると、単一の接続をオープン/クローズするたびに、ロック ファイルが作成/削除されます。この操作は非常に遅く、アプリケーション内でデータベースをすばやく開いたり閉じたりすると (多数のアトミック クエリを実行すると)、この問題が発生する可能性があります。

問題を調査して解決するには、いくつかの方法があります。

すべてのオープン/クローズ コール
をトレースする 接続をオープンおよびクローズするたびに表示されるデバッグ トレースを追加します。
ネストされた接続と、接続プールが無駄になっている場所を検出できます。

接続ポーリングを強制 する 簡単な「修正」は、接続文字列に接続プールを明示的に設定することです。これはデフォルトの動作である必要があるため、問題を解決するために何もしない可能性がありますが、非常に単純であるため、試さない理由はありません。

OLE DB Services=-1

接続マネージャー クラスを使用して、接続を作成/解放します。
新しい OleDbConnection の明示的な作成とクローズ操作をすべて独自のコードに置き換えます。これにより、アプリケーション全体で既存の 1 つの接続を常に再利用でき、動作を 1 か所に集中させることで、アプリ全体をすばやく微調整できます。

では、単一の接続を保持することが一般的に推奨されないのはなぜでしょうか?

  • 一般に、アプリケーション全体で接続を開いたままにしないでください。これは、データベース サーバーがリソースを利用できるようにしておく必要があり、接続できるクライアントの数が減少するためです (利用できる接続の数には常に制限があります)。
    サーバー部分のないファイルベースのデータベースであるAccessの場合、新しい接続を開く(ロックファイルの作成)に関連する遅延があるため、実際には単一の接続を開いたままにしておくことが望ましいです。Access は多数の同時ユーザーで使用することを意図していないため、接続を開いたままにしておくリソース コストは問題になるほど重要ではありません。
    簡単なテストから、接続を常に開いたままにしておくと、後続の接続が約 10 倍速く開くことができることがわかります。

  • OleDb ドライバーは接続プールを行うため、解放された接続を再利用できます。

  • 接続とデータベース操作を小さく抑えておくことで、スレッドの使用時に同時実行の問題が発生する可能性が低くなります。データベースへの同じパイプラインを使用して複数の操作を実行している場合、グローバル接続を維持することが問題になる場合があります。

于 2011-06-16T04:28:55.903 に答える
2

私にとって何年もうまく機能する情報を追加するだけです(David-W-Fentonが提案するものと多少似ています)

まず、OleDbConnectionMicrosoft Access (MDB、JET) は接続プールを使用していません。Microsoft が KB191572 で述べているように:

Jet OLE DB プロバイダーと ODBC ドライバーを使用する接続はプールされません。これらのプロバイダーとドライバーはプールをサポートしていないためです。

接続プーリングに関しては、Ivan Mitev による次のブログ投稿もあります。

では、これはどういう意味ですか?アクティブに開かれた接続が存在することで、複数の接続を閉じたり開いたりするテストがはるかに高速 (2 ~ 3 倍) になったことは明らかです。私にとって唯一可能な説明は、アクティブな接続がなくなるたびに接続プールが解放されるということです。さらに調査を行い、Microsoft Data Access Components の Pooling のようなものを読む必要があります。または、プールを維持するためだけに、開いている単一の接続を保持することもできます。これは醜いですが、それでも十分な回避策です! 誰かがより良いアイデアを持っている場合は、共有してください。

また、Microsoftは MSDN で次のように述べています

ADO Connection オブジェクトは暗黙的に IDataInitialize を使用します。ただし、これは、一意のユーザーごとにインスタンス化された Connection オブジェクトの少なくとも 1 つのインスタンスをアプリケーションが常に維持する必要があることを意味します。そうしないと、その文字列の最後の Connection オブジェクトが閉じられたときに、プールが破棄されます。

これらすべてと私自身のテストに基づいて、Microsoft Access データベースでも接続プールを「シミュレート」する私のソリューションは、おおよそ次の手順に従います。

  1. OleDbConnectionアプリケーション ライフサイクルのできるだけ早い段階で Access データベースを開きます。
  2. 通常の SQL クエリを実行し、OleDbConnection推奨どおりに s をできるだけ早く破棄します。
  3. OleDbConnectionアプリケーションのライフサイクルのできるだけ遅い段階で、常に開いているものを破棄します。

これにより、アプリケーション (主に WinForms) の速度が大幅に向上しました。

これは、接続プーリングをサポートしていないように見える Sqlite でも機能することに注意してください。

于 2014-08-08T06:10:43.590 に答える