提问人:ProgrammerKyle 提问时间:11/9/2023 最后编辑:CraigProgrammerKyle 更新时间:11/10/2023 访问量:57
如何通过 VB.Net 在 Azure SQL 数据库上执行完全异步查询?
How to execute a totally asynchronous query on an Azure SQL Database via VB.Net?
问:
我有一个连接到 Azure SQL Server 的 ASP.Net 网站。
我需要执行一个存储过程,该过程主要由插入语句组成,运行大约需要 8 分钟。
我通常会通过网站 VB.Net 代码中的 SqlCommand.ExecuteNonQuery 来执行此操作。
但是,在这种情况下,由于运行时间为 8 分钟,这样做会导致网站超时。
我需要一种方法来异步执行此查询,以便网站将命令发送到服务器并立即恢复操作,而无需等待结果。当我稍后检查相关表格时,如果出现问题,将很明显。
我无法使用 Service Broker,因为 Azure 不允许这样做,而且如果没有 Azure 托管实例,我无法设置作业。
我尝试过 SqlCommand.BeginExecuteNonQuery,它确实允许我单击代码后面的按钮,然后立即返回到网站中执行其他操作,但似乎没有实际运行查询,我猜这是因为我的代码到达事件的末尾并在查询实际完成之前取消查询。
有没有办法做到这一点?
当前代码...
Protected Sub Button_Click(sender As Object, e As System.EventArgs) Handles Button.Click
txtUsrID.Value = Session.Item("s_lngUsrID")
txtUsrTypIDfk.Value = Session.Item("s_lngUsrTypIDfk")
'Set up the command variables
Dim Cnn As SqlConnection
Dim Cmd As SqlCommand
Cnn = New SqlConnection
Cnn.ConnectionString = "TheString"
Cmd = New SqlCommand
Cmd.CommandType = Data.CommandType.StoredProcedure
'Retrieve the record count
Cmd.CommandText = "sptblTemp_GndrRprtPrGrp_Insrt"
Cmd.Parameters.Add("@UsrIDfk", Data.SqlDbType.Int).Direction = Data.ParameterDirection.Input
Cmd.Parameters("@UsrIDfk").Value = txtUsrID.Value
Try
Cnn.Open()
Cmd.Connection = Cnn
Cmd.CommandTimeout = 0
Cmd.BeginExecuteNonQuery()
Catch Excptn As Exception
txtMssgs.Value = Excptn.Message
End Try
'clean up
Cmd.Parameters.RemoveAt("@UsrIDfk")
'close the connection if it's open
If Cnn.State = Data.ConnectionState.Open Then
Cnn.Close()
End If
Cmd.Dispose()
Cnn.Dispose()
End Sub
答:
- 将一个模块添加到您的 ASP 项目中,将其命名为 “公共模块”。
- 在该模块中,您将把代码和结果作为 Public、子例程和 Public 结果对象。
- 在按钮单击中,您可以检查 Result 对象是否为 什么都没有或空的。如果是,请创建一个线程来调用该子例程,该子例程执行 查询并填充 Public Result。第一次单击将创建线程/查询/结果。线程将继续 8分钟,然后做它的事情。
该公共结果对象将永远保留在该 IIS 进程中,直到该进程回收为止。
由于这需要 8 分钟,因此您可能需要设置一个变量来告知下一个用户/下一个单击查询正在进行中。
在所示代码中,问题在于承载执行的对象仅在本地过程作用域中,并且您正在关闭连接并在例程结束时释放连接和命令对象---在这种情况下,而不执行任何操作来等待查询完成。在它完成之前,您不希望在该作用域中调用它来保留它,因为它会阻塞并最终在功能上与您之前执行的操作相同。BeginExecuteNonQuery
SqlCommand
EndExecuteNonQuery
解决方案是确保 和 对象都托管在更高级别的范围内,以便您可以等待关闭和释放,直到查询完成执行。我会怀疑使用 a,因为它不会被实例化,因此多个用户之间可能存在冲突问题。某种实例可能更有意义。BeginExecuteNonQuery
SqlCommand
SqlConnection
Module
Class
您还可以将 / 工作流与 一起使用。这将需要较少的代码重构,因为编译器将生成类来为您保留幕后。为此,您可以添加到声明中,然后将该行更改为 .Async
Await
ExecuteNonQueryAsync
SqlCommand
Async
Sub
Cmd.BeginExecuteNonQuery
Await Cmd.ExecuteNonQueryAsync
评论
ExecuteNonQueryAsync
BeginExecuteNonQuery
ExecuteNonQueryAsync
BeginExecuteNonQuery
Async
Await