【发布时间】:2020-02-17 10:27:26
【问题描述】:
我有一个在 MS Access 中开发的应用程序,它使用 ADO 连接到 SQL Server (Microsoft SQL Server 2017) 来执行大量存储过程。 ADO 连接都是通过应用程序角色完成的,以限制权限。
在最新的更新中,我创建了一些新的存储过程,它们返回多个记录集,并粘贴在 Excel 中。我的问题是,当我执行这些存储过程时,应用程序角色被删除......查询运行没有任何问题,但是当它完成运行时,应用程序角色未设置。
以下是在 VBA Access 中调用的存储过程之一的示例:
Public Function CDTExceptionsReport() As ADODB.Recordset
On Error GoTo ErrorHandler
Set objConn = DB.MaintainConnection
On Error GoTo 0
If objCmd_ER Is Nothing Then
Set objCmd_ER = New ADODB.Command
With objCmd_ER
.CommandType = adCmdText
.CommandTimeout = 60 ' increase command
.CommandText = "EXEC tool.ExceptionsReport;"
.Prepared = True
' set connection object
.ActiveConnection = objConn
End With
End If
Set CDTExceptionsReport = objCmd_ER.Execute
On Error GoTo 0
Exit Function
ErrorHandler:
MsgBox "Error: " & Err.DESCRIPTION & vbNewLine & "Number: " & Err.Number
On Error GoTo 0 ' reset error handling
End Function
注意objConn 是我的连接对象,objCmd_ER 是我的全局命令对象。
通过 VBA 中的即时终端,我可以在调试模式下使用以下命令检查正在激活的角色:
Set RS = objConn.Execute("SELECT CURRENT_USER")
?RS.Fields(0)
如果我在objCmd_ER.Execute 行之前运行它,我可以看到应用程序角色仍在使用中。但是,当我在该语句之后立即运行它时,应用程序角色被删除并返回我的 Windows 用户名。有谁之前经历过这个吗?
我已经直接在 SQL Server 中执行了这个存储过程,它工作正常并且不会注销应用程序角色。因此我的想法是它与 ADO 连接有关。
请让我知道提供哪些进一步的详细信息会有所帮助。存储过程不包含任何 DDL 或 DML 语言 - 只有 4 个选择查询。
谢谢
【问题讨论】:
-
请注意,应用程序角色不能很好地与连接池配合使用。在关闭连接之前使用
sp_unsetapprole,如here 所述。 -
谢谢,@DanGuzman - 有很多存储过程会重复执行。您是否建议我必须在我调用的每个存储过程之前和之后(分别)设置和取消设置 approle?由于我在这里提到的,我倾向于不关闭连接,因为下一个存储过程永远不会超过 30 秒。
-
不是在每次调用之前设置/取消设置,而是在每个连接打开后设置,并在连接关闭/关闭之前取消设置。否则,您需要禁用连接池。
-
我确实在打开连接后设置了应用程序角色。我从不关闭连接;我认为他们最终会超时。会不会跟这有关系?
-
如果您从不关闭连接或通过连接字符串关闭池,则使用应用程序角色的连接池将不是问题。我怀疑您遇到的问题是因为 ADO 正在背后打开连接,因为指定的连接已在使用中。在调试器中运行
SELECT @@SPID;,看看session id是否不同。
标签: sql-server vba ms-access ado