簡體   English   中英

在哪里關閉SqlDataReader對象和SqlConnection對象?

[英]Where to close SqlDataReader object and SqlConnection object?

我調用一個函數,該函數將SqlDataReader對象返回到調用語句。 我很困惑應該在哪里關閉SqlDataReader對象和SqlConnection對象? 在函數中還是在調用之后?

這是函數調用:

SqlDataReader dr2= RetrieveSearcher();
pid = dr2[0].ToString();

這是功能:

protected SqlDataReader RetrieveSearcher()
{
    String Q = "select price from tb3 where pid='12';
    cn = new SqlConnection("data source=.\\sqlexpress; integrated security=true; initial catalog=singh");
    cn.Open();

    cmd = new SqlCommand(Q,cn);
    dr1 = cmd.ExecuteReader();
    dr1.Read();

    return dr1;
}
  1. 始終使用參數化查詢來避免SQL注入攻擊並提高性能(大多數數據庫服務器可以通過適當的查詢重用執行計划)
  2. 切勿將連接斷開的時間超過必要!
  3. 不要共享數據庫連接! 創建,使用,銷毀它。
  4. 將所有實現IDisposable的內容包裝在using塊中,例如Connections,Commands,DataReaders等。這可確保即使發生異常也不會保持打開資源的狀態。
  5. 在您的數據庫架構中使用正確的類型並讀取這些類型,請勿將所有內容一一轉換為字符串! price示例似乎確實應該是十進制或數字值,而不是字符串,因此請勿將其存儲為字符串,也不要將其讀回為字符串。
  6. 通過名稱從app.config或web.config(取決於應用程序類型)中檢索連接字符串,請勿將字符串硬編碼到您的連接或其他任何地方。

關於你的邏輯

更改您的方法以返回自定義類型,例如一條數據。 這樣可以確保適當的SoS(關注點分離)。 不要返回DataReader! 這將從調用者那里提取整個數據庫調用,這是您應該努力的目標。

protected SomeType RetrieveSearcherData(string pid)
{
    const string Q = "SELECT price FROM tb3 WHERE pid = @pid";
    using(var cn=new SqlConnection())
    using(var cmd=new SqlCommand(Q,cn))
    {
        // I do not know what pid is but use tho correct type here as well and specify that type using SqlDbType
        cmd.Parameters.Add(new SqlParameter("@pid", SqlDbType.VarChar, 100) { Value = pid});
        cn.Open();
        using(var dr1= cmd.ExecuteReader())
        {
            if(dr1.Read())
            {
               var result = dr1.GetDecimal(0);
               // read something and return it either in raw format or in some object (use a custom type)
            }
            else
              return null; // return something else that indicates nothing was found
        }
    }
}
  1. 您是否真的想在每次調用此功能時打開一個連接? 讓一個線程處理多個連接是獲得死鎖的肯定方法。

  2. 如果您仍然想做#1,我建議您讓RetrieveSearcherList<T>或heck的形式返回所需的DataTable ,只需返回一個DataTable並進行處理即可。 這樣,函數可以關閉其打開的連接。

  3. 如果您仍然真的想返回SqlDataReader則需要確保可以關閉打開的連接。 SqlDataReader不會直接公開SqlConnection ,因此,在離開RetrieveSearcher方法后, 無法直接關閉連接。 但是,您可以這樣做:

     dr1 = cmd.ExecuteReader(CommandBehavior.CloseConnection); 

    當閱讀器關閉時,這將關閉連接。 因此,您可以執行以下操作:

     using (SqlDataReader dr2 = RetrieveSearcher()) { pid=dr2[0].ToString(); } 

我當然假設您確實需要多個字符串。 :)如果您只需要一個字符串,則只需返回該字符串並調用cmd.ExecuteScalar();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM