[英]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(" ", " ").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(" ", " ").Replace("\n", "<br />");
ProgressPanel.Update();
}
其中ProgressPanel是AJAX驱动的UpdatePanel,所有内容均加载在其中。
脚本现在到达阶段2 RAISERROR,这时会触发FinishExport,并且我没有收到其他InfoMessage事件。 GetExportResults永远不会触发,因此整个页面基本上在该位置挂起。 我想念什么?
无法异步更新标签-Web应用程序无法正常工作。 页面执行时,它将HTML发送到浏览器,然后被销毁。 没有简单的过程可以继续将更新的HTML发送到浏览器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.