2015-12-09 53 views
0

嗨我想在C#中創建CRUD函數,但我堅持我的第一個是FetchALL,迄今爲止它說並不是所有的代碼路徑都返回一個值。C#getAll函數的建議

繼承人到目前爲止我的代碼

public SqlDataReader FetchAll(string tableName) 
     { 



     using (SqlConnection conn = new SqlConnection(_ConnectionString,)) 
    { 

    string query = "SELECT * FROM " + tableName; 
    SqlCommand command = new SqlCommand(query, conn); 
    using (SqlDataReader reader = command.ExecuteReader()) 
    conn.Open(); 


    conn.Close(); 
      } 
     } 
    } 
} 

我可以給你更多的信息,感謝

+5

你永遠不會返回任何東西,但你聲明瞭函數返回一個'SqlDataReader'。此外,SQL注入可能在'string query =「SELECT * FROM」+ tableName;'中。 –

+2

如果你確實選擇返回'SqlDataReader',確保它被調用者正確關閉和處置,否則很容易開始泄漏sql連接。 –

+2

不要害怕嘗試自己解釋錯誤。閱讀並盡力理解。並非所有的代碼路徑(即不是每個執行路徑)都返回值。這可以通過確保所有路徑返回一個值來迎合/解決。問問你自己是否至少有一個回報聲明可以一直到達。開始包括一個! –

回答

5

您的退貨類型爲SqlDataReader,但您沒有在代碼中任何地方返回任何內容。至少,你應該申報的數據讀取器並返回它是這樣的:

public SqlDataReader FetchAll(string tableName) 
{ 
    SqlDataReader reader; 

    using (SqlConnection conn = new SqlConnection(_ConnectionString)) 
    { 

     string query = "SELECT * FROM " + tableName; 

     // added using block for your command (thanks for pointing that out Alex K.) 
     using (SqlCommand command = new SqlCommand(query, conn)) 
     { 
      conn.Open(); // <-- moved this ABOVE the execute line. 
      reader = command.ExecuteReader(); // <-- using the reader declared above. 
      //conn.Close(); <-- not needed. using block handles this for you. 
     } 
    } 

    return reader; 
} 

注意,我已經注意到,我看到還有一些其他問題,您可以通過我的意見看。

此外,我想指出一些非常重要的事情:您應該始終避免查詢中的字符串連接,因爲這會使您面臨SQL注入攻擊的風險(正如gmiley正式指出的那樣)。在這種情況下,您應該創建一個枚舉,其中包含與所有可能的表名稱關聯的值,然後使用字典根據枚舉值查找表名。如果用戶提供了一個無效/未知值,那麼你會拋出一個參數異常。


這不是你的問題的結束,雖然(如默認已經指出)。您不能在using塊中創建連接,該塊在退出該塊後立即處置並關閉,然後使用該方法返回的SqlDataReader。如果我是你,我會返回一個DataSet而不是SqlDataReader。以下是我想做到這一點:

首先,創建可能的表值的枚舉:

public enum Table 
{ 
    FirstTable, 
    SecondTable 
} 

這表枚舉值映射到表的名稱(你將在你的靜態構造函數填充字典):

private static Dictionary<Table, string> _tableNames = new Dictionary<Table, string>(); // populate this in your static constructor. 

然後這裏是你的方法獲取數據:

public static System.Data.DataSet FetchAll(Table fromTable) 
{ 
    var ret = new System.Data.DataSet(); 

    using (var conn = new System.Data.SqlClient.SqlConnection(_connectionString)) 
    { 
     string tableName = ""; 
     if (!_tableNames.TryGetValue(fromTable, out tableName)) throw new ArgumentException(string.Format(@"The table value ""{0}"" is not known.", fromTable.ToString())); 
     string query = string.Format("SELECT * FROM {0}", tableName); 

     using (var command = new System.Data.SqlClient.SqlCommand(query, conn)) 
     { 
      using (var adapter = new System.Data.SqlClient.SqlDataAdapter(command)) 
      { 
       adapter.Fill(ret); 
      } 
     } 
    } 

    return ret; 
} 

最後一點需要注意的是,我建議你在每個會議中以較低的駱駝事例命名你的課程級變量,例如, _connectionString

+1

我刪除了我的答案,因爲你的答案更清晰,因爲你正在修復一些各種問題,爲了完整性,我會在這裏提到一對:SQL注入是這個函數的最大問題,如果你必須這樣做,把表名放在字典中,並使用枚舉查找字符串值。此外,該參數在使用前從未被檢查過。 – gmiley

+0

@gmiley - 啊偉大的一點!我從來沒有看過實際的SQL。正在更新... –

+0

更新了我的評論以提供解決SQL注入問題的方法。 – gmiley

1

你需要一個回statment用於返回一個值的方法。

5

首先,你沒有從方法中返回任何東西。我會補充,你確定要返回一個SqlDataReader嗎?它是在一個使用塊中聲明的,所以它在你返回時會被關閉。我認爲你應該重新評估這個函數應該返回什麼。

+0

謝謝你我只需要返回一些東西,否則函數不會被gridview拾取,但我不確定我需要返回的結果 – Lewis