return ステートメントは、using ステートメントがデータベースへの接続を閉じることを防ぐことができますか?
-
09-09-2019 - |
質問
一時テーブルを作成しているときに、一時テーブルがすでに存在することを示すエラー メッセージが表示されます。一時テーブルはセッションに固有であるため、接続が適切に閉じていないようです。using ステートメント内の return ステートメントに関係があるのではないかと思います。
次のコードがあります。
using (IDbConnection connection = dbConnectionHandler.CreateConnection())
{
connection.Open();
CreateATempTable();
PopulateTempTable();
DataSet ds = CallStoredProcThatUsesTempTable();
return ds;
}
この種のコードを複数の場所で使用して、同じ名前の一時テーブルを作成します。
残念ながら、次のエラーが発生します。 There is already an object named '#MyTempTable' in the database
.
これで、一時テーブルはセッションに固有のものであるため、セッションが閉じられると消えるはずであることがわかりました。
この原因として考えられることが 3 つあります...
- connection.Close() を呼び出す必要があります
- return ステートメントを using ステートメントの外側に配置する必要があります
- 戻る前に作成した一時テーブルを削除する必要があります
それがどれであるか知っている人はいますか?それとも私が思いつかなかったものなのか?
解決
私はここで推測しますが、データベース接続プールの設定を確認しています。オフプーリング回してみて、それが助けかどうかを確認します。
あなたは.NETライブラリレベルでの接続を処分/閉じたときには通常、実際のデータベース・サーバーの接続は閉じられません。それはちょうど、データプロバイダ内の接続プールに戻され、プログラムは同じパラメータおよび資格情報を使用して別の接続を要求したときに再利用されます。私は、データベースセッションが開いているトランザクションと、おそらくいくつかの基本的なパラメータを除いて、プールに戻される前に、どのような方法でリセットされないと思います。より高価なオブジェクトは、一時テーブルのように、放置されています。
あなたは(非常に非効率的な)オフプーリング変えることができます。それとも、それを作成しようとする前に、一時テーブルの有無をチェックし、それが存在する場合はその内容を削除することができます。それとも、接続を閉じる前に一時テーブルをドロップすることができます。
他のヒント
私はconnection.Dispose()(したがってconnection.Close()だけでなく)が呼び出されることをかなり確信しています。
あなたは)その簡単に1を実行して、十分な)と2を検証し、問題がまだ存在することを確認することができます。解決策は、おそらく3)と説明はコネクションプーリングだろう。
電源サイクルが発生しない限り、または他のいくつかの深刻な奇妙なコーナーケース処分が呼び出されます。
あなたが証明をしたい場合は、オブジェクトをラップし、中にブレークポイントを置いています。
を使用してブロックがボンネットの下にブロックし、最後に/のtry / catchに翻訳されています。はい、それは使用してブロック内のリターンに関係なく処分されます。
いいえ、connection.Closeは常に内部的にのはのtry / finallyブロックでそれを置きます。
を使用しているために呼び出されますまた、接続プーリングを検討する必要があります。 TransactionScopeであなたのコードをラップしてみます。
質問に答えるには:
- using ステートメントは、接続の Dispose メソッドが呼び出されたときに、暗黙的に接続を閉じます。
- それは必要ないはずです: http://aspadvice.com/blogs/name/archive/2008/05/22/Return-Within-a-C_2300_-Using-Statement.aspx
- それを試してみてください。
そのクラスはIDisposableをも使用してブロック内のreturn文が存在している場合は、オブジェクトを配置します文を使用します。
それはあなたの#temptableを保持し、接続プーリングであるは、手動でそのテーブルを削除する場合があります。
は、使用中のデータベース接続ライブラリの詳細を知らなくても、私はそれが最初の二つのどちらだと思うだろう。 using
は、メソッドの外に戻ったときに簡単にそのようなリソースをクリーンアップするために特異的に導入されました。それは、Javaまたは類似の通常try...finally
ブロックへの直接似ています。
は、換言すれば、ブロックとreturn
方法を残すDispose
は、そのような実装の正気を想定し、そのプロセスの一部としてClose
メソッドを呼び出す必要が接続上で呼び出されます。
ここで重要なポイントは、 "まともな実装" です。
これは、接続プーリングによって引き起こされています。あなたがトランザクションで何をしているかラップ、そして最後に、それをロールバックします。または、DSを移入した後、一時テーブルをドロップします。