更新我是否必须澄清我的问题?我很惊讶地看到我在两周内没有得到任何评价,评论或回答。
我正在尝试编写一个简单的winforms应用程序,该应用程序异步执行SQL SELECT语句。当sql server开始返回结果时,我想执行一个事件处理程序,我已连接到SqlCommand的StatementCompleted事件。
表单包含两个按钮,一个文本框和一个标签。单击button1时,我创建SqlCommand并连接事件处理程序,然后打开SqlConnection并调用BeginExecuteReader以启动异步操作。我设置标签以显示命令正在执行。
在事件处理程序中,我只需设置标签即可显示命令已完成。
单击按钮2时,我更改标签以显示我们正在处理结果。然后我调用EndExecuteReader并将其返回值分配给新的SqlDataReader,然后我处理它。
我看到的是,当命令准备好时,不会调用事件处理程序。相反,当我的代码完成处理EndExecuteReader返回的阅读器时,它会被调用。
我在这里遗漏了什么吗?我是否误解了事件的预期用途?我试图找到一个StatementCompleted的例子,但我只能找到它的一般描述,没有工作代码。 SqlCommand.BeginExecuteReader page at MSDN的示例使用循环并等待IAsyncResult.IsCompleted属性为true。我希望在属性获得同时,StatementCompleted事件会触发。
public Form1() {
InitializeComponent();
}
private IAsyncResult iAsyncResult;
private SqlCommand sqlCommand;
private void statementCompleted(object sender,
StatementCompletedEventArgs e) {
label1.Text = "Statement completed";
}
private void button1_Click(object sender, EventArgs e) {
var northWindConnection =
new SqlConnection(
"Data Source=.\\SqlExpress;Initial Catalog=Northwind;" +
"Integrated Security=True;" +
"asynchronous processing=true");
sqlCommand = new SqlCommand("WAITFOR DELAY '00:00:05';" +
" SELECT * FROM [Order Details]",
northWindConnection);
sqlCommand.StatementCompleted += statementCompleted;
northWindConnection.Open();
iAsyncResult = sqlCommand.BeginExecuteReader();
label1.Text = "Executing";
}
private void button2_Click(object sender, EventArgs e) {
label1.Text = "Not waiting anymore, reading";
var results = new StringBuilder();
var reader = sqlCommand.EndExecuteReader(iAsyncResult);
while (reader.Read()) {
for (int i = 0; i < reader.FieldCount; i++) {
results.Append(reader[i].ToString() + "\t");
}
results.Append(Environment.NewLine);
}
reader.Close();
sqlCommand.Connection.Close();
textBox1.Text = results.ToString();
}
答案 0 :(得分:2)
事件的顺序如下:
SqlCommand.BeginExecuteReader(callback, stateObject)
将T-SQL发送到SQL Server,命令开始执行。AsyncCallback
的{{1}}。BeginExecuteReader()
以获取对EndExecuteReader()
对象的引用。SqlDataReader
来阅读查询结果。这可以是一行,也可以是数百万行。 在返回所有请求的数据之前,查询未完成。 SqlDataReader
事件 - 但前提是查询/存储过程未使用StatementCompleted
。换句话说,当T-SQL完全完成时调用SET NOCOUNT ON
,包括所有相关的数据传输。
答案 1 :(得分:1)
为可能遇到此问题的任何人添加此项,因为几个月前它被问到没有提供答案。
StatementCompleted事件在对SqlCommand应用异步调用模式时没有用。它确实被解雇但只是在调用EndExecuteReader期间,这基本上已经太晚了。如果您想要实现一般的异步调用模式,this MSDN article可以很好地解释它是如何完成的。 BeginExecuteReader documentation中的示例代码显示了异步模式下SqlCommand的正确用法。
答案 2 :(得分:0)
我怀疑这种行为的线索是事件的“ StatementCompletedEventArgs”参数包含属性“ RecordCount”,该属性是受语句影响的行数。
在实际数据全部发送完之后,MS SqlServer(以及之前的Sybase SqlServer)将受影响的行数作为单独的“消息”(宽松地使用术语)返回。
另外,请注意:一个Sql Command可以由许多SQL语句组成,每个SQL语句都可以影响许多行,因此返回许多“受影响的行”。因此,我认为对于给定的SQL命令,该事件可能会触发多次;或根本没有使用SET NOCOUNT ON。