繁体   English   中英

在.NET Web Control中异步显示存储过程PRINT语句

[英]Asynchronously showing Stored Procedure PRINT statements within .NET Web Control

我编写了一个很长的存储过程,该过程是从ASP.NET(3.5)页面调用的。

存储过程如下所示:

CREATE PROCEDURE csi_CourseEval_Export
   @year
   @term
   @use_case
AS
BEGIN
   SET NOCOUNT ON
   PRINT 'Building candidate course list'
   .... -- do stuff
   PRINT ''
   RAISERROR('1', '0', 1) WITH NOWAIT -- flush buffer and indicate step 1 reached
   PRINT ''
   .... -- do more stuff
   PRINT ''
   RAISERROR('2', '0', 1) WITH NOWAIT -- flush buffer and indicate step 2 reached
   PRINT ''
   .... -- do more stuff
   PRINT ''
   RAISERROR('3', '0', 1) WITH NOWAIT -- flush buffer and indicate step 3 reached
   PRINT ''
   .... -- do more stuff
   .... -- do LOTS more stuff, including steps 4 through 8
   PRINT ''
   RAISERROR('9', '0', 1) WITH NOWAIT -- flush buffer and indicate step 9 reached
   PRINT ''       

   RAISERROR('DONE', '0', 1) WITH NOWAIT -- flush buffer and indicate completion

END

我的C#代码隐藏具有以下相关的属性和方法:

    private SqlConnection db;
    private string exportState = "";
    private static string jdbConnectionString = "Data Source=...;Initial Catalog=...;Persist Security Info=True;Asynchronous Processing=true;User ID=...;Password=...";

    private void ShowData(GridView display, string table)
    {
        display.DataSource = new SqlDataSource(CoursEval.jdbConnectionString, "SELECT * FROM ##" + table);
        display.DataBind();
    }

    private void SetControls(bool enable)
    {
        RunExport.Enabled = enable;

        if (enable)
            RunExport.Text = "Run";
        else
            RunExport.Text = "Running";

        UseCase.Enabled = enable;
        Year.Enabled = enable;
        Term.Enabled = enable;
    }

    private void LogSQL(string message)
    {
        if (message.Length == 1 || message.Equals("DONE"))
        {
            exportState = message;
        }
        SQL_Log.Text += "<br />" + message.Replace(" ", "&nbsp;").Replace("\n", "<br />");
    }

    protected void RunExport_Click(object sender, EventArgs e)
    {
        db = new SqlConnection(jdbConnectionString);

        db.FireInfoMessageEventOnUserErrors = true;            
        db.InfoMessage += delegate(object ds, SqlInfoMessageEventArgs de)
        {
            LogSQL(de.Message);              
        };
        db.Open();

        SqlCommand cmd = new SqlCommand("csi_CourseEval_Export", db);
        cmd.Parameters.Add("@year", SqlDbType.VarChar).Value = Year.SelectedValue;
        cmd.Parameters.Add("@term", SqlDbType.VarChar).Value = Term.SelectedValue;
        cmd.Parameters.Add("@use_case", SqlDbType.VarChar).Value = UseCase.SelectedValue;
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.CommandTimeout = 0;

        SetControls(false);
        cmd.ExecuteNonQuery();

        ShowData(ShowCourses, "Courses");
        ShowData(ShowStudents, "Students");
        ShowData(ShowFaculty, "Faculty");

        ResultsPanel.Visible = true;

        db.Close();
        SetControls(true);
    }

以下System.Web.UI.WebControls.*表单对象相关:

SQL_Log                                - Label
RunExport                              - Button
UseCase, Year and Term                 - DropDownList 
ShowCourses, ShowFaculty, ShowStudent  - GridView
ResultsPanel                           - Panel

症状:
无论我做什么, SQL_Log标签在存储过程的最后只更新一次,而其他所有内容都显示出来。

所需的行为:
SQL_Log标签应该异步更新,让用户可以看到存储过程已经走了多远。

我究竟做错了什么?

编辑:这是部分答案:

更新为使用异步SqlCommand(BeginExecuteNonQuery代替ExecuteNonQuery)使我进入第一个RAISERROR,但是在调用EndExecuteNonQuery之后,即使存储过程仍在运行,我也没有收到任何其他InfoMessage事件。

RunExport_Click现在看起来像:

    protected void RunExport_Click(object sender, EventArgs e)
    {
        db = new SqlConnection(CoursEval.jdbConnectionString);

        db.FireInfoMessageEventOnUserErrors = true;            
        db.InfoMessage += delegate(object ds, SqlInfoMessageEventArgs de)
        {
            LogSQL(de.Message);              
        };
        db.Open();

        SqlCommand cmd = new SqlCommand("csi_CourseEval_Export", db);
        cmd.Parameters.Add("@year", SqlDbType.VarChar).Value = Year.SelectedValue;
        cmd.Parameters.Add("@term", SqlDbType.VarChar).Value = Term.SelectedValue;
        cmd.Parameters.Add("@use_case", SqlDbType.VarChar).Value = UseCase.SelectedValue;
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.StatementCompleted += GetExportResults;
        cmd.CommandTimeout = 0;

        SetControls(false);

        cmd.BeginExecuteNonQuery(new AsyncCallback(FinishExport), cmd);

    }

现在,我还有三个附加功能,ShowResults,GetExportResults和FinishExport:

    private void ShowResults()
    {
        ShowData(ShowCourses, "Courses");
        ShowData(ShowFaculty, "Faculty");
        ShowData(ShowFacultyEnrollment, "FacultyEnrollment");
        ShowData(ShowStudents, "Students");
        ShowData(ShowStudentEnrollment, "StudentEnrollment");

        ResultsPanel.Visible = true;

    }


    private void FinishExport(IAsyncResult result)
    {
        if (result.IsCompleted)
        {
            SqlCommand cmd = (SqlCommand)result.AsyncState;

            cmd.EndExecuteNonQuery(result);
        }
        else
        {
            RunExport.Text = exportState;
        }
    }

    private void GetExportResults(object sender, StatementCompletedEventArgs e)
    {
        ShowResults();

        db.Close();
        SetControls(true);
    }

此外,LogSQL现在看起来像这样:

    private void LogSQL(string message)
    {
        if (message.Length == 1 || message.Equals("DONE"))
        {
            exportState = message;
        }

        SQL_Log.Text += "<br />" + message.Replace(" ", "&nbsp;").Replace("\n", "<br />");
        ProgressPanel.Update();
    }

其中ProgressPanel是AJAX驱动的UpdatePanel,所有内容均加载在其中。

脚本现在到达阶段2 RAISERROR,这时会触发FinishExport,并且我没有收到其他InfoMessage事件。 GetExportResults永远不会触发,因此整个页面基本上在该位置挂起。 我想念什么?

无法异步更新标签-Web应用程序无法正常工作。 页面执行时,它将HTML发送到浏览器,然后被销毁。 没有简单的过程可以继续将更新的HTML发送到浏览器。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM