「接続を開く」とはどういう意味ですか?
-
27-09-2019 - |
質問
私は誰かにその理由を説明しようとしていました データベース接続 「接続を開く」ことが実際に何を意味するのか本当にわからないことに気付いたときに、Idisposableを実装します。
だから私の質問は - C#が接続を開くと実際に何をするのでしょうか?
ありがとうございました。
解決
実際、接続の実装には2つのクラスが含まれています(実際にはそれ以上ですが、単純化しています)。
これらの1つはです IDbConnection
実装 (SQLConnection
, NpgsqlConnection
, OracleConnection
, 、など)あなたがあなたのコードで使用するもの。もう1つは、アセンブリの内部であり、コードには見えない「実際の」接続オブジェクトです。これを呼びます」RealConnection
「今のところ、実際の名前は異なる実装によって異なります(例:NPGSQLでは、私が実装に最も精通している場合ですが、クラスは呼び出されます NpgsqlConnector
).
あなたがあなたを作成するとき IDbConnection
, 、それはありません RealConnection
. 。データベースで何かをしようとすると、失敗します。あなたがいつ Open()
その後、次のことが起こります。
- プーリングが有効になっている場合、aがあります
RealConnection
プールで、それをデクにし、それを作りますRealConnection
のためにIDbConnection
. - プーリングが有効になっている場合、そして
RealConnection
存在するオブジェクトは最大サイズよりも大きく、例外をスローします。 - それ以外の場合は、新しいものを作成します
RealConnection
. 。 ITを初期化します。これには、何らかのネットワーク接続(TCP/IPなど)またはファイルハンドル(アクセスなど)を開き、ハンドシェーキング用のデータベースのプロトコル(データベースタイプとは異なります)を使用し、接続を許可します。これは次のようになりますRealConnection
のためにIDbConnection
.
で実行された操作 IDbConnection
操作に変わります RealConnection
ネットワーク接続(または何でも)で行います。結果は実装オブジェクトに変わります IDataReader
プログラミングのために一貫したインターフェイスを提供するために。
もし IDataReader
で作成されました CommandBehavior.CloseConnection
, 、その後、DataReaderが「所有権」を取得します RealConnection
.
あなたが電話するとき Close()
次に、次のいずれかが起こります。
- プーリングし、プールがいっぱいでない場合は、オブジェクトがキューに入れられ、後の操作で使用されます。
- それ以外の場合
RealConnection
接続を終了するためのプロトコル定義の手順(接続がシャットダウンされることをデータベースに信号する)を実行し、ネットワーク接続などを閉じます。その後、オブジェクトは範囲外に落ちて、ガベージコレクションで利用できるようになります。
例外は、 CommandBehavior.CloseConnection
ケースが発生しましたが、その場合はそうです Close()
また Dispose()
に呼ばれている IDataReader
それはこれを引き起こします。
あなたが電話するなら Dispose()
その後、同じことがによるものです Close()
. 。違いはそれです Dispose()
「クリーンアップ」と見なされ、 using
, 、 その間 Close()
生涯の真ん中に使用される可能性があり、後で続く可能性があります Open()
.
の使用のため RealConnection
オブジェクトとそれらがプールされているという事実は、接続を開閉して閉じます。比較的重いものから比較的軽いものに変わります。したがって、接続を長時間開いたままにすることが重要ではなく、それらを開くオーバーヘッドを避けるために、可能な限り短時間開いたままにすることが重要になります。 RealConnection
あなたのためのオーバーヘッドを扱い、それらをより迅速に使用すればするほど、プールされた接続がより効率的に使用されます。
また、大丈夫です Dispose()
an IDbConnection
あなたがすでに呼んでいること Close()
on(それは常に安全に電話してもよいというルールです Dispose()
, 、状態が何であれ、実際にはすでに呼ばれていても)。したがって、手動で電話をかけていた場合 Close()
に接続を持っているのはまだ良いでしょう using
ブロック、電話がかかる前に例外が発生する場合をキャッチする Close()
. 。唯一の例外は、実際に接続を開いたままにしたい場合です。あなたが戻ってきたとします IDataReader
で作成されました CommandBehavior.CloseConnection
, 、その場合、あなたはそれを処分しません IDbConnection
, 、 しかし 行う 読者を処分します。
接続を処分できない場合、 RealConnection
再利用のためにプールに返されたり、シャットダウン手順を経たりしません。プールが制限に達するか、基礎となる接続の数がパフォーマンスを損傷し、作成されることをより多くブロックするポイントまで増加します。最終的にファイナリザーはオンになります RealConnection
呼び出され、これが修正されることにつながる可能性がありますが、ファイナライゼーションは損傷を減らすだけで、依存することはできません。 ( IDbConnection
そうであるように、最終的なものは必要ありません RealConnection
これにより、管理されていないリソースやシャットダウンを行う必要があります)。
また、 IDbConnection
これを超えて、上記を分析しても必要ではないと信じるようになったとしても、それは廃棄されるべきです(例外はいつ CommandBehavior.CloseConnection
すべての処分負担を渡します IDataReader
, 、しかし、その読者を処分することも同様に重要です)。
他のヒント
良い質問。
SQL接続の「フード下」の動作に関する私の(やや限られた知識)から、次のような多くのステップが関係しています。
ボンネットの下のステップ
- 物理ソケット/パイプが開かれています(与えられたドライバーを使用して、たとえばODBC)
- SQL Serverでの握手
- 接続文字列/資格情報が交渉されました
- トランザクションスコーピング
接続プーリングは言うまでもなく、何らかのアログリズムが関係していると思います(接続文字列が既存のプールの場合、接続文字列が1つと一致する場合、接続がプールに追加され、そうでなければ新しいものが作成されます)
idiposable
SQL接続に関しては、IDISPOSABLEを実装して、処分を呼び出すと(使用指令または説明を介して)、接続を接続プールに戻すようにします。これは、単純な古いsqlconnection.close()だけとはまったく対照的です。
私の理解から、.close()はデータベースへの接続を閉じますが、.dispose()は.close()を呼び出します。 それから 管理されていないリソースをリリースします。
これらのポイントを念頭に置いて、少なくともIdisposableを実装することをお勧めします。
上記の回答に加えて...重要なのは、「接続を開く」リソースを割り当てると、標準的なガベージコレクション以上のものを回復するために、つまり、Somekindのオープンソケット/パイプ/IPCを回復することです。 dispose()メソッドはこれらをクリーンアップします。