簡體   English   中英

如何同時執行 DataAdapter.Fill()

[英]How to execute DataAdapter.Fill() simultaneously

我已經在 ASP.Net 應用程序上工作了很長時間,並且有超過 10 個客戶端在使用該應用程序。 但是現在我在應用程序中發現了一個問題,就是我有一個存儲過程調用,大約需要30秒才能執行。 這不是問題,因為 SQL 代碼高度復雜且循環多次。 問題是:每當執行該存儲過程調用時,我都無法使用任何其他函數或存儲過程調用。 當我嘗試調試時,問題是 'DataAdapter.Fill()' function 正在等待第一個存儲過程調用完成。

我執行存儲過程調用並返回數據的代碼是:

public static DataSet ExecuteQuery_SP(string ProcedureName, object[,] ParamArray)
    {
        SqlDataAdapter DataAdapter = new SqlDataAdapter();       
        DataSet DS = new DataSet();
        try
        {
            if (CON.State != ConnectionState.Open)
                OpenConnection();
            SqlCommand cmd = new SqlCommand();
            cmd.CommandTimeout = 0;
            cmd.CommandText = ProcedureName;
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Connection = CON;
            cmd.Transaction = SqlTrans;
            string ParamName;
            object ParamValue;
            for (int i = 0; i < ParamArray.Length / 2; i++)
            {
                ParamName = ParamArray[i, 0].ToString();
                ParamValue = ParamArray[i, 1];
                cmd.Parameters.AddWithValue(ParamName, ParamValue);
            }
            DataAdapter = new SqlDataAdapter(cmd);
            DataAdapter.Fill(DS);
            cmd.CommandText = "";
        }
           catch (Exception ea)
        {
        }
        return DS;
    }

所有存儲過程調用都通過這個 function 工作。 因此,當我的第一個存儲過程調用“A”正在運行時,存儲過程調用“B”在“A”完成之前不會執行。

這會降低應用程序的整體性能並導致數據檢索出現問題。 我瀏覽了谷歌,發現“線程”可能會有所幫助,但我無法正確執行線程。 我對這類事情不是很熟悉。 如果您可以糾正問題,這將很有幫助。 我的第一個存儲過程調用是:

 ds = DB.ExecuteQuery_SP("SelectOutstandingReportDetailed", parArray);

其中 ds 是數據集 object。 第二個存儲過程調用是:

ds = DB.ExecuteQuery_SP("[SelectAccLedgersDetailsByID]", ParamArray);

我當前打開的數據庫連接 function 是:

 public static bool OpenConnection() 
        {
            try
            {

                    Server = (String)HttpContext.GetGlobalResourceObject("Resource", "Server");
                    DBName = (String)HttpContext.GetGlobalResourceObject("Resource", "DBName");
                    UserName = (String)HttpContext.GetGlobalResourceObject("Resource", "UserName");
                    PassWord = (String)HttpContext.GetGlobalResourceObject("Resource", "PassWord");

                    string ConnectionString;
                    ConnectionString = "server=" + Server + "; database=" + DBName + "; uid=" + UserName + "; pwd=" + PassWord + "; Pooling='true';Max Pool Size=100;MultipleActiveResultSets=true;Asynchronous Processing=true";

                    CON.ConnectionString = ConnectionString;
                    if (CON.State != ConnectionState.Open)
                    {
                        CON.Close();
                        CON.Open();
                    }

            }
            catch (Exception ea)
            {
            }
            return false;
        }

其中 'CON' 是一個公共 SqlConnection 變量

static SqlConnection CON = new SqlConnection();

我發現了問題,就是所有的存儲過程調用都是通過這個'CON' object來執行的。 如果每個存儲過程調用都有單獨的 SqlConnection object,則沒有問題。 那么是否可以為每個 ExecuteQuery_SP 調用創建單獨的 SqlConnection 。 如果有任何疑問,請發表評論。 謝謝

默認情況下,SQL 服務器將同時允許數千個連接 這不是您問題的根源。 您已強制對存儲過程的每次調用都通過一個方法進行匯集。 排除您對存儲過程的調用 - 換句話說,丟失 ExecuteQuery_SP 方法,這是一個瓶頸。 然后再次測試。

這是對數據層的介紹。

這是我可以為您創建的最簡單的版本。 重要提示:要了解您應該閱讀有關 async-await 的信息。

您可以從Microsoft C# Async-Await Docs開始

// TODO set up your connection string
    private string connectionString = "<your connection string>";

    // Gets data assyncronously
    public static async Task<DataTable> GetDataAsync(string procedureName, object[,] ParamArray)
    {
        try
        {
            var asyncConnectionString = new SqlConnectionStringBuilder(connectionString)
            {
                AsynchronousProcessing = true
            }.ToString();

            using (var conn = new SqlConnection(asyncConnectionString))
            {
                using (var SqlCommand = new SqlCommand())
                {
                    SqlCommand.Connection = conn;
                    SqlCommand.CommandText = procedureName;
                    SqlCommand.CommandType = CommandType.StoredProcedure;

                    string ParamName;
                    object ParamValue;
                    for (int i = 0; i < ParamArray.Length / 2; i++)
                    {
                        ParamName = ParamArray[i, 0].ToString();
                        ParamValue = ParamArray[i, 1];
                        SqlCommand.Parameters.AddWithValue(ParamName, ParamValue);
                    }

                    conn.Open();
                    var data = new DataTable();
                    data.BeginLoadData();
                    using (var reader = await SqlCommand.ExecuteReaderAsync().ConfigureAwait(true))
                    {
                        if (reader.HasRows)
                            data.Load(reader);
                    }
                    data.EndLoadData();
                    return data;
                }
            }
        }
        catch (Exception Ex)
        {
            // Log error or something else
            throw;
        }
    }

    public static async Task<DataTable> GetData(object General, object Type, string FromDate, string ToDate)
    {
        object[,] parArray = new object[,]{
        {"@BranchID",General.BranchID},
        {"@FinancialYearID",General.FinancialYearID},
        {"@Type",Type},
        {"@FromDate",DateTime.ParseExact(FromDate, "dd/MM/yyyy", System.Globalization.CultureInfo.InvariantCulture)},
        {"@ToDate",DateTime.ParseExact(ToDate, "dd/MM/yyyy", System.Globalization.CultureInfo.InvariantCulture)}
        };

        return await DataBaseHelper.GetDataAsync("SelectOutstandingReportDetailed", parArray);
    }

    // Calls database assyncronously
    private async Task ConsumeData()
    {
        DataTable dt = null;

        try
        {
            // TODO configure your parameters here
            object general = null;
            object type = null;
            string fromDate = "";
            string toDate = "";

            dt = await GetData(general, type, fromDate, toDate);
        }
        catch (Exception Ex)
        {
            // do something if an error occurs
            System.Diagnostics.Debug.WriteLine("Error occurred: " + Ex.ToString());
            return;
        }

        foreach (DataRow dr in dt.Rows)
        {
            System.Diagnostics.Debug.WriteLine(dr.ToString());
        }
    }

    // Fired when some button is clicked. Get and use the data assyncronously, i.e. without blocking the UI.
    private async void button1_Click(object sender, EventArgs e)
    {
        await ConsumeData();
    }

暫無
暫無

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

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