簡體   English   中英

我是否可以在C#函數中適當關閉此SQL連接?

[英]Am I closing this SQL connection in a C# function appropriately?

為了試圖解決有關保持打開狀態並超過最大池數的連接的問題 ,我試圖重寫用於連接數據庫的函數。

該函數存在於本地編譯的庫中。 使用反射器,我可以看到代碼如下:

public SqlProvider([Optional, DefaultParameterValue("")] string StrConnection)
{
    string str;
    if (StrConnection == "")
    {
        str = ConfigurationSettings.AppSettings["ConStr"];
    }
    else
    {
        str = StrConnection;
    }
    SqlConnection connection = new SqlConnection(str);
    connection.Open();
    this.MyCommand = new SqlCommand();
    SqlCommand myCommand = this.MyCommand;
    myCommand.Connection = connection;
    myCommand.CommandType = CommandType.Text;
    myCommand = null;
    this.MyDataAdapter = new SqlDataAdapter(this.MyCommand);
    this.MyCommandBuilder = new SqlCommandBuilder(this.MyDataAdapter);
    this.MyDataSet = new DataSet();
}

我正計划對此進行閱讀

public SqlProvider([Optional, DefaultParameterValue("")] string StrConnection)
{
    string str;
    if (StrConnection == "")
    {
        str = ConfigurationSettings.AppSettings["ConStr"];
    }
    else
    {
        str = StrConnection;
    }

    using (SqlConnection connection = new SqlConnection(str))
    {
        connection.Open();
        this.MyCommand = new SqlCommand();
        SqlCommand myCommand = this.MyCommand;
        myCommand.Connection = connection;
        myCommand.CommandType = CommandType.Text;
        myCommand = null;
        this.MyDataAdapter = new SqlDataAdapter(this.MyCommand);
        this.MyCommandBuilder = new SqlCommandBuilder(this.MyDataAdapter);
        this.MyDataSet = new DataSet();
    }
}

然后重新編譯dll。 假定通常在公共類的頂部創建SQLProvider()的實例,然后在類成員中使用該實例(例如:

public class Banner
{
    DSLibrary.DataProviders.SqlProvider db = new DSLibrary.DataProviders.SqlProvider(Defaults.ConnStr);
    public Banner()
    {    
    }

    public DataTable GetBannerImages(string bannerLocation,int DeptId)
    {
        using (DSLibrary.DataProviders.SqlProvider db = new DSLibrary.DataProviders.SqlProvider(Defaults.ConnStr))
        {
            DataTable dt = new DataTable();

            //Add Parameter @BannerLocation for Banner of Specific Location 
            //Call proc_getBannerImages Stored procedure for Banner Images
            db.AddStoredProcParameter("@BannerLocation", SqlDbType.VarChar, ParameterDirection.Input, 100, bannerLocation);
            db.AddStoredProcParameter("@DeptId", SqlDbType.Int, ParameterDirection.Input, 0, DeptId);
            dt = db.ExecuteStoredProcedure("proc_getBannerImages");
            return dt;
        }
    }
}

我要這樣做正確嗎? 在我看來,連接將在實際檢索數據之前被處理掉。 另外,Visual Studio告訴我SQLProvider()必須隱式轉換為System.IDisposable我將如何實現這一點?

我試過在using (DSLibrary.DataProviders.SqlProvider db = new DSLibrary.DataProviders.SqlProvider(Defaults.ConnStr)){}語句中包裝class Banner所有成員,但是intellisense然后在類struct中顯示“ Invalid using (DSLibrary.DataProviders.SqlProvider db = new DSLibrary.DataProviders.SqlProvider(Defaults.ConnStr)){} ” ,或接口成員聲明”錯誤。

最好的方法是什么?

更新我曾嘗試拆解調整和重新編譯DSLibrary,但是正如CHris_Lively所說,我認為它對我沒有任何幫助。 到目前為止,將有問題的實例更改為我認為是更標准的格式是可行的:

public DataTable GetBannerImages(string bannerLocation,int DeptId)
{
    using (SqlConnection conn = new SqlConnection(Defaults.ConnStr))
    {
        SqlCommand cmd = new SqlCommand("proc_getBannerImages", conn);
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add(new SqlParameter("@BannerLocation", bannerLocation));
        cmd.Parameters.Add(new SqlParameter("@DeptId", DeptId));

        SqlDataAdapter da = new SqlDataAdapter();
        da.SelectCommand = cmd;
        DataTable dt = new DataTable();

        da.Fill(dt);
        return dt;
    }
}

我將要研究企業庫,看來這可能是前進的方向。

不建議將連接保留的時間不要超過要求的時間(另請參見“ 提高.NET應用程序的性能和可伸縮性: Microsoft Press的模式和實踐”的第14章)。

在實踐中,我將更改您的類,以使其不具有SqlConnection(或SqlDataAdapterSqlCommandBuilder )作為類的成員(如果必須 ,則應實現IDisposable模式),而是創建新實例,並使用using語句包裝關於需要使用它們的類方法。

我認為您的做法不正確。 一旦您到達using塊的末尾,SqlConnection變量將變得不可用。 如果要在構造函數外部使用它,請不要在SqlConnection變量周圍使用using {}(sqlcommand變量MyCommand在構造函數外部間接使用它)。
相反,讓您的SqlProvider類實現IDisposable,然后在其中的MyCommand,MyDataAdapter,MyDataSet等變量上調用Dispose。
您可能在SqlProvider類中應該有以下內容:

    public void Dispose()
    {
        if (MyCommand != null)
        {
            MyCommand.Dispose();
        }
        //... Similarly for MyDataAdapter,MyDataSet etc.
    }

如果要在using塊中使用它,您的類需要實現IDisposable接口。 有關dispose()和IDisposable的准則,請參見http://msdn.microsoft.com/zh-cn/library/system.idisposable.dispose%28v=VS.100%29.aspx

你近了 但是,有幾個問題。

首先,整個DSLibrary似乎根本沒有買任何東西。

進行數據訪問時,通常需要在獲取連接和執行命令具有相同功能的地方進行結構化。 您的方法只應返回操作結果。 這樣,您可以干凈地使用連接,命令和閱讀器的IDisposable接口。

以下示例使用企業庫 請注意,Db沒有using子句。 它沒有實現IDisposable。 相反,該命令在超出范圍時負責釋放連接:

    public static DataTable GetBannerImages(String bannerLocation, Int32 departmentId)
    {
        DataTable result = new DataTable();
        result.Locale = CultureInfo.CurrentCulture;

        Database db = DatabaseFactory.CreateDatabase("NamedConnectionStringFromConfig");

        using (DbCommand dbCommand = db.GetStoredProcCommand("proc_getBannerImages"))
        {
            db.AddInParameter(dbCommand, "BannerLocation", DbType.String, bannerLocation);
            db.AddInParameter(dbCommand, "DeptId", DbType.Int32, departmentId);

            using (IDataReader reader = db.ExecuteReader(dbCommand))
            {
                SopDataAdapter dta = new SopDataAdapter(); // descended from DbDataAdapter

                dta.FillFromReader(result, reader);
            } // using dataReader
        } // using dbCommand

        return result;
    } // method::GetBannerImages

您可能已經擁有將讀取器轉換為數據表的功能,如果不只是研究System.Data.Common.DbDataAdapter類的子類,

我在企業庫方面取得了巨大的成功。 這是快速,高效的,並且在執行此路由時,我從未遇到內存泄漏或數據庫連接問題。

無需將變量設置為null無論如何它們將被GC刪除。

您還需要為實現IDisposable所有類調用Dispose()Close() 例如SqlConnection

您可以手動執行以下操作:

SqlConnection conn = null;
try
{
    // use conn
}
finally
{
    if (conn != null)
        conn.Close();
}

或自動使用using塊:

using (SqlConnection = new SqlConnection())
{
    // use conn
}

(像你一樣做)

您還可以使用運算符來減少代碼?

string str = String.IsNullOrEmpty(StrConnection) ? ConfigurationSettings.AppSettings["ConStr"] : StrConnection;

??

string str = StrConnection ?? ConfigurationSettings.AppSettings["ConStr"];

暫無
暫無

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

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