2017-02-27 72 views
1

我有一個奇怪的用例,就是如何處理一段代碼中的SQL連接。爲了驗證這一點,我已經創建了一個單元測試:SQL Server連接錯誤塊後續連接

var masterBuilder = new SqlConnectionStringBuilder("Server=CHILTERN8564;Integrated Security=SSPI"); 
var databaseBuilder = new SqlConnectionStringBuilder(masterBuilder.ConnectionString); 
databaseBuilder.InitialCatalog = "CoreIssue"; 

using (var conDatabase = new SqlConnection(databaseBuilder.ConnectionString)) 
{ 
    Assert.Throws<SqlException>(conDatabase.Open); // crash as DB does not exist 
} 

using (var conMaster = new SqlConnection(masterBuilder.ConnectionString)) 
{ 
    // let's create the DB 
    conMaster.Open(); 
    new SqlCommand("CREATE DATABASE CoreIssue", conMaster).ExecuteNonQuery(); 
} 

using (var conDatabase = new SqlConnection(databaseBuilder.ConnectionString)) 
{ 
    // CRASH! even if the DB exists. 
    conDatabase.Open(); 
    new SqlCommand("CREATE TABLE Bob(name varchar(10))", conDatabase).ExecuteNonQuery(); 
} 

基本上後的第一個連接拋出,因爲DB不存在,最後一投爲好,顯然是因爲DB是一個「破」的狀態?

如果我刪除第一個using塊一切正常,如果我慢慢地調試並逐步完成代碼(等待最後一次查詢之前幾秒鐘),一切正常。

任何想法可能會導致此行爲?

+0

如果將MultipleActiveResultSets = true,會發生什麼情況;在你的連接字符串?只是好奇。 – manderson

+0

不是即時創建數據庫。我認爲這裏發生的事情是你的第一個USING因爲數據庫不存在而死掉,但第二個工作正常,但是sql server仍然在創建數據和日誌文件,所以當你的第三個查詢沒有完成時執行。這就是爲什麼一切工作,如果你慢慢地通過代碼。 –

+0

我想到了這一點,但它並沒有解釋爲什麼,如果第一個「使用」不在那裏,一切正常......這是第一次使用那些似乎導致問題的死亡... – Tallmaris

回答

1

所以MultipleActiveResultSets沒有幫助,但我發現了兩個解決方案,如果你設置:

databaseBuilder.Pooling = false; 

或致電

SqlConnection.ClearAllPools(); 

所以測試將是:

[Test] 
public void Test() 
{ 
    var masterBuilder = new SqlConnectionStringBuilder(@"Server=localhost\sqlexpress;Integrated Security=SSPI"); 
    var databaseBuilder = new SqlConnectionStringBuilder(masterBuilder.ConnectionString); 
    databaseBuilder.InitialCatalog = "CoreIssue"; 
    //databaseBuilder.Pooling = false; <- fixes problem 

    using (var conDatabase = new SqlConnection(databaseBuilder.ConnectionString)) 
    { 
     Assert.Throws<SqlException>(conDatabase.Open); // crash as DB does not exist 
    } 

    SqlConnection.ClearAllPools(); //<- also fixes problem 

    using (var conMaster = new SqlConnection(masterBuilder.ConnectionString)) 
    { 
     // let's create the DB 
     conMaster.Open(); 
     new SqlCommand("CREATE DATABASE CoreIssue", conMaster).ExecuteNonQuery(); 
    } 

    using (var conDatabase = new SqlConnection(databaseBuilder.ConnectionString)) 
    { 
     // CRASH! even if the DB exists. 
     conDatabase.Open(); 
     new SqlCommand("CREATE TABLE Bob(name varchar(10))", conDatabase).ExecuteNonQuery(); 
    } 

顯然這並不能真正解釋爲什麼墜毀的連接在泳池周圍並重新使用......