2017-06-14 29 views
0

運行在我的應用程序凍結下面的方法時,當我暫停VS似乎被卡住對雲行:C#到SQL的ExecuteReader()陷入

SqlDataReader reader = select.ExecuteReader(); 

我有其他SQL方法運行良好,所以我知道連接字符串是正確的,我已經仔細檢查了SQL,這很好。我認爲reader變量在ExecuteReader()被調用時不能包含標量函數的返回值嗎?

public static bool AccountValidation(string username, string password) 
{ 
    string statement = "select dbo.AccountValidation('" + username + "','" + password + "')"; 
    SqlCommand select = new SqlCommand(statement, connect); 
    connect.Open(); 
    SqlDataReader reader = select.ExecuteReader(); 
    string result = reader.ToString(); 
    connect.Close(); 

    if (result != "true") 
    { 
     return false; 
    } 
    else 
    { 
     return true; 
    } 
} 
+2

稍微不相關,但你真的應該考慮參數化你的查詢,因爲你目前的方法可能會讓你容易受到像SQL注入這樣的糟糕。 –

+0

你期望reader.ToString()能做什麼?你的意思是做select.ExecuteScalar()而不是? –

+0

我不是第一個說,但重申,**參數化您的查詢**。您的代碼可能容易受到SQL注入攻擊。你還應該考慮在'using'語句中包裝實現'IDisposable'的對象。 – maccettura

回答

3

主要問題是您實際上沒有從數據讀取器讀取任何內容,您必須遍歷結果集,然後根據序號/位置索引進行讀取。

也有像

  • 不使用留下的代碼容易受到SQL注入式攻擊參數等大問題。
  • 沒有將您的一次性元件包裝在using塊中,如果有例外,可能會使數據庫連接保持打開狀態
  • 在類型中共享數據庫連接。根據需要創建連接,然後在完成後處置它們。

這是您的更新代碼與修復。我猜對列類型(varchar),修正它們以及它們在模式中實現的長度。

public static bool AccountValidation(string username, string password) 
{ 
    const string statement = "select dbo.AccountValidation(@username, @password)"; 
    string result = null; 

    // reference assembly System.Configuration 
    string connStr = System.Configuration.ConfigurationManager.ConnectionStrings["YourDb"].ConnectionString; 

    using(var connection = new SqlConnection(connStr)) 
    using(SqlCommand cmd = new SqlCommand(statement, connect)) 
    { 
     cmd.Parameters.Add(new SqlParameter("@username", SqlDbType.VarChar, 200){Value = username}); 
     cmd.Parameters.Add(new SqlParameter("@password", SqlDbType.VarChar, 200){Value = password}); 
     connect.Open(); 
     using(SqlDataReader reader = cmd.ExecuteReader()) 
     { 
      if(reader.Read()) 
       result = reader.GetString(0); // read back the first column of the first row 
     } 
    } 
    if (result != "true") 
    { 
     return false; 
    } 
    else 
    { 
     return true; 
    } 
} 

在一個側面說明,這將是更清潔,以便從數據庫功能AccountValidation返回bit然後閱讀回用reader.GetBoolean(0)並分配到結果,並返回,而不是直接做字符串比較。

另外,正如上面在評論中提到的那樣,如果您只返回1個值,那麼調用ExecuteScalar而不是ExecuteReader會更容易(代碼更少)。

+1

除了底部多餘的if語句(OP不是你),這是一個完美的答案。 – maccettura

1

string result = reader.ToString(); 

而且之前添加行

reader.Read(); 

,請您參數化查詢。

+0

'reader.ToString()'不會返回第一個序號結果。很可能它只會返回默認的完整類型名稱。 'reader.GetString(0)'會。 – Igor

0

我沒有足夠的聲望留下評論,但要回答部分問題,是的,您可以使用SqlDataReader讀取帶有或不帶列別名的單個標量結果。