2009-05-04 26 views
3

特定のデータベースを削除して再作成した後、次回同じデータベース上の新しい接続に対してコマンドを実行しようとすると、SQL Serverで接続が切断される問題が発生します。 、私が得る:(私は別のサーバーに接続しようとした場合)ここでSql Server 2008データベースが破棄された後の接続の終了

A transport-level error has occurred when sending the request to the server. (provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.)

は、TCPのバージョンである。ここ

A transport-level error has occurred when sending the request to the server. (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.)

は、問題をREPROする手順は、次のとおりです

  1. オープンデータベースへの接続やSQL実行コマンド
  2. ドロップデータベース
  3. データベース
  4. を開き、同じデータベースへの新しい接続を再作成し、
、それに対してコマンドを実行しようとします

結果:私はここで例外

を受け取るには、コードです:

using (var conn = new System.Data.SqlClient.SqlConnection("Data Source=.;Initial Catalog=DBNAME;Integrated Security=True")) 
{ 
    conn.Open(); 
    var cmd = conn.CreateCommand(); 
    cmd.CommandText = "UPDATE ..."; 
    cmd.ExecuteNonQuery(); 
} 

string sql = "Alter Database DBNAME set single_user with rollback immediate drop database DBNAME"; 
var server = new Microsoft.SqlServer.Management.Smo.Server("."); 
server.ConnectionContext.ExecuteNonQuery(sql); 
server.ConnectionContext.Disconnect(); 

sql = File.ReadAllText("PathToDotSqlFile...")); 
server = new Microsoft.SqlServer.Management.Smo.Server("."); 
server.ConnectionContext.ExecuteNonQuery(sql); 
server.ConnectionContext.Disconnect(); 

using (var conn = new System.Data.SqlClient.SqlConnection("Data Source=.;Initial Catalog=WER_CONFIG;Integrated Security=True")) 
{ 
    conn.Open(); 
    var cmd = conn.CreateCommand(); 
    cmd.CommandText = "UPDATE ..."; 
    cmd.ExecuteNonQuery(); 
} 

エラーは 'cmd.ExecuteNonQuery()'行の最後にあります。私が接続するたびに新しい接続を作成していても、SQL Serverは何か(またはおそらくADO.netコード)を追跡しているので、次に接続を求めるときに、すでに使用されているものが表示されますまたはサーバー側でクローズされています。それはあなたがそれに対して別のコマンドを実行しようとするまで、それがサーバーによって閉じられたことを認識しません(おそらく、それが接続されているデータベースのためです)。

初期クエリを実行する最初のステップを実行せず、データベースを削除して再作成してコマンドを実行するだけで、このエラーは発生しません。データベースが破棄される前に初期接続を確立することは、このエラーの重要な部分です。

また、私はそうのようなデータベースをドロップして再作成する外部プロセスを使用して試してみました:

ProcessStartInfo info = new ProcessStartInfo("sqlcmd.exe", " -e -E -S . -Q \"Alter Database DBNAME set single_user with rollback immediate drop database DBNAME\""); 
var p = Process.Start(info); 
p.WaitForExit(); 

info = new ProcessStartInfo("sqlcmd.exe", " -i " + PathToDotSqlFile); 
p = Process.Start(info); 
p.WaitForExit(); 

そして、それは助けにはなりませんでした。

新しいSqlConnectionを作成し、それがプールからではなくクリーンであることを確認する方法はありますか?この問題を解決する方法に関する他の提案はありますか?

更新:SqlConnection.ClearPool()を使用して問題を解決しましたが、私は接続文字列を編集してpooling = falseとすることもできました。

答えて

7

ADO.NETは自動的に接続プールを管理します。アプリケーションで接続を「閉じる」と、同じ接続文字列で接続を要求した場合に備えて、接続はプールに戻され、保持されます。これはあなたの "新しい"接続が古くなっている理由です。

接続文字列にパラメータとしてpooling=falseを追加することで、この動作を無効にすることができます。

3

SQL2008についてはわかりませんが、アプリケーション側の接続プーリングの問題のように思えます。古い時代には、 "OLEDB Services = -1"を接続文字列に追加して、接続プーリングを無効にしました。おそらくこれを行うもっとエレガントな方法があります。

編集:ADO.Net 2.0は、SQLConnectionオブジェクトにClearPool関数を追加したようです。 (http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.clearpool(VS.80).aspx)これがうまくいくかどうかは非常に興味があります。

関連する問題