2017-01-02 12 views
0

私はいくつかのSQL Serverデータベースとやり取りするC#プログラムを作っています。問題は、データベース(dbA)に接続し、この接続を閉じて、別のデータベースを別のデータベース(dbB)に開き、dbAの復元を実行すると、そのデータベース(dbA)が使用中であることをSqlExceptionがトリガします。しかし、私はプログラムを実行し、dbBにのみ接続する場合、私は問題なく、最初の接続が格納されているように他のデータベースを復元することができます。とにかく、ここでの接続を開閉する必要があり、コードは次のとおりです。C# - SQL接続が閉じない

private bool CheckConnection() 
    { 
     bool res = false; 
     string conString = string.Empty; 
     if (!String.IsNullOrEmpty(serverBox.Text) && !String.IsNullOrEmpty(dbBox.Text)) 
     { 
      conString = ConcatConString(dbBox.Text); 
      using (SqlConnection conn = new SqlConnection(conString)) 
      { 
       conn.Open(); 
       if (conn.State == ConnectionState.Open) 
       { 
        res = true; 
       } 
      } 
     }   
     return res; 
    } 
+0

ADO.NETは接続プールを使用します。つまり、接続は「リセット」され、再利用のためにプールに保持されます。アプリケーションを終了するか、復元する前にすべてのクライアントを切断する必要があります。 –

+0

スタックトレースを使用して完全な例外の詳細を追加してください。また、このメソッドを呼び出すコードを共有してください。 –

+0

復元はすべてのユーザーが保存しようとしていたものを失うことになるので、これは大きな問題ではありません。最良の選択肢は、データベースをシングルユーザーモードにすることです。[ここに示す](http://dba.stackexchange.com/questions/101917/unable-to-restore-database-backup-because-it-is-accessed- by-other-connection)を使用して、アクティブなトランザクションをロールバックし、修復者を実行してデータベースをマルチユーザーモードに戻します。 –

答えて

3

ADO.NETは高価な接続オブジェクトを再利用するために接続プーリングを使用します。接続を閉じると、既存のトランザクションはすべてロールバックされ、サーバー側の状態はリセットされ、次のOpenコマンドの接続プールに配置されます。

サーバーには、サーバーのシャットダウン、データベースの復元などの劇的な操作を実行しようとすると、依然としてサーバー接続としてカウントされます。つまり、明示的な操作を行い、サーバーにOKを続行します。この場合

、あなたはその後、例えば、バックマルチユーザーモードにそれを持って、シングルユーザーモードにデータベースを設定し、リストア操作を実行する必要があります。

ALTER DATABASE [MyDB] SET SINGLE_USER WITH ROLLBACK IMMEDIATE 
RESTORE DATABASE [MyDB] ... 
ALTER DATABASE [MyDB] SET MULTI_USER 

SSMSを経由して何をするかだ、とき

既存の接続に時間を掛けたい場合は、WITH ROLLBACK AFTER xx SECONDSを使用することもできます。ただし、この場合はデータベースを上書きします。

+0

データベースを復元するときに 'ALTER DATABASE [MyDB] SET MULTI_USER'が不要かもしれないと思います。データベースをマルチユーザモードに自動的に戻すと思います。 –

+0

これは、「接続を閉じる」にチェックを入れるとSSMSが生成するスクリプトです。また、データを検証したり、差分バックアップを行う前に、 'RESTORE'がDBAの背後でデータベースモードを変更した場合は、むしろ不愉快になります。 [RESTORE](https://msdn.microsoft.com/en-us/library/ms186858.aspx)コマンドには、接続モードに影響するオプションはありません –

+0

ありがとうございます!私は間違いなくそれを試してみましょう、良い解決策のように思えます –

0

接続を閉じるデータベースでそれを閉じていない、それだけでADO.Netによって維持プールへの接続を返します。通常はこれを提案することはありませんが、接続プーリングを無効にする正当な理由があるようです。

接続文字列でPooling属性をnoまたはfalseに設定すると、接続は実際にサーバー上で閉じる必要があります。

あなたがそれを有効にするか、次のコードでは無効になっコネクションプーリングとSSMSでsp_who2を実行することにより、どのように機能するかを観察することができます:

class Program 
{ 
    static void Main(string[] args) 
    { 
     SqlConnectionStringBuilder bldr = new SqlConnectionStringBuilder(); 
     bldr.IntegratedSecurity = true; 
     bldr.InitialCatalog = "YourDB"; 
     bldr.DataSource = "(localdb)\\YourServer"; 
     bldr.Pooling = false; //Comment and uncomment this and run sp_who2 

     using (SqlConnection con = new SqlConnection(bldr.ConnectionString)) 
     { 
      con.Open(); 
     } 
    } 
} 

更新

は、あなたのプログラムがない限りこれをしないでください接続する唯一のものです。私は、プログラムが特にデータベースを復元するためのものだったという印象を受けました。データベースに他のクライアントがある場合、これはパフォーマンスを左右します。

+2

プールを無効にする理由はありません。復元中にSINGLE USERモードを使用する方がずっと簡単です。 –

+0

私はその質問を誤解したと思う。 – Crowcoder

関連する問題