2016-04-15 71 views
4

我連接到SQL Server 2012數據庫以基於ID查詢單個值。 (值得一提的是,這個數據庫位於我的開發機器的另一個大陸的服務器上,因此延遲時間非常長,大約在100ms左右)。SqlDataReader HasRows = True,但沒有數據

查詢似乎成功執行。 SqlDataReader對象的HasRows屬性設置爲true,所以我嘗試使用該值來分配變量。當我正常運行程序時,我遇到一個異常消息'Given key was not present in the dictionary'。如果我停止執行並檢查SqlDataReader對象,並枚舉結果。首先我告訴'enumeration yielded no results',然後當我繼續執行我得到的消息'invalid attempt to read when no data is present'

這裏不同的例外是有問題的代碼:

SqlConnection sql_conn = new SqlConnection(ConnectionString); 
SqlCommand sql_cmd = new SqlCommand(String.Format("select ItemType from ItemTable where ItemID='{0}'", item_id), sql_conn); 

Console.WriteLine(sql_cmd.CommandText); 

sql_conn.Open(); 

SqlDataReader rdr = sql_cmd.ExecuteReader(); 

rdr.Read(); 

if (rdr.HasRows) //True 
{ 
    item_type= TypesMap[rdr["ItemType"].ToString()]; //Either 'given key not found in dictionary' or 'invalid attempt to read when no data is present' 
} 

我已經在SQL Server Management Studio和SQL語句執行它是成功的。我已經嘗試將一個ItemID硬編碼到C#代碼中的語句中,並且存在相同的錯誤。

我還能做些什麼來調試呢?一切似乎都沒問題,直到我嘗試訪問查詢的結果。

+2

不會導致這個問題**但**:我會顛倒順序,首先使用'HasRows'來檢查是否有任何行,然後使用'Read'將讀取器推進到下一個記錄。 –

+0

這兩個錯誤消息是由兩種完全不同的情況造成的。用這段代碼收到的是什麼? – Steve

+1

我會跳過reader.HasRows並執行邏輯,如 'if(reader.Read()){item_type = TypesMap [rdr [「ItemType」]。ToString()]; }' – Nino

回答

2

你必須調試:似乎TypesMap沒有從數據庫中讀取密鑰:

// Wrap IDisposable into using 
using (SqlConnection sql_conn = new SqlConnection(ConnectionString)) { 
    // Make SQL readable 
    // Make SQL parametrized (and not formatted) when it's possible 
    String sql = 
    @"select ItemType 
     from ItemTable 
     where ItemID = @prm_ItemId"; 

    // Wrap IDisposable into using 
    using (SqlCommand sql_cmd = new SqlCommand(sql, sql_conn)) { 
    // I don't know ItemID's type that's why I've put AddWithValue 
    sql_cmd.Parameters.AddWithValue("@prm_ItemId", item_id); 

    // Wrap IDisposable into using 
    using (SqlDataReader rdr = sql_cmd.ExecuteReader()) { 
     // rdr.HasRows is redundant - rdr.Read() returns true if record has been read 
     if (rdr.Read()) { 
     String key = Convert.ToString(rdr.GetValue(0)); 
     // Put break point here: what is the "key" value? 
     item_type = TypesMap[key]; 
     } 
    } 
    } 
} 

編輯:盧克在註釋中提到,病因的錯誤是,鍵比較預計將是大小寫不敏感,所以修改是解釋.Net如何比較鍵:

var TypesMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); 

... 
TypesMap.Add("aBc", "xyz"); 
String test = TypesMap["Abc"]; // return "xyz"; notice "aBc" and "Abc" 
+0

謝謝。這與最終的數據庫查詢無關。和往常一樣,這只是一個愚蠢的錯誤,我需要使字典鍵全部小寫。 – Luke

+1

@Luke:更好的選擇是*不*使鍵小寫,而是分配合適的*比較器*:'TypesMap = new Dictionary ('StringComparer.OrdinalIgnoreCase);' –

+0

我沒有意識到這一點。謝謝! – Luke

2

正如德米特里所指出的那樣,「給定的鍵未找到......」不是數據庫的東西,而是字典的東西。 下面我已經添加了一個簡單的檢查,以確保密鑰在字典中 - 如果是,那麼我們可以將其分配給item_type。

此外,如果HasRows()沒有按照您的期望執行操作,請嘗試以下操作。這是我從DB讀取的標準方式:

using (SqlDataReader results = sql_cmd.ExecuteReader(CommandBehavior.CloseConnection)) 
{ 
    while (results.Read()) 
    { 
     string Key = rdr["ItemType"].ToString(); 
     if (TypesMap.ContainsKey(Key)) 
      item_type = TypesMap[Key];  
    } 
} 
0

我轉換:

dto.Id = (int)record["Id"]; 

要:

dto.Id = (int)record[0]; 

這爲我工作。