为什么我的数据库命令总是调用 sp_describe_first_result_set?

Why are my database Commands always calling sp_describe_first_result_set?

背景

我正在维护一个 VB.Net(以前称为 VB6)实用程序,可将记录导出到平面文件。我们的一位客户报告说新版本 运行 花费了很长时间,并且深入研究跟踪很容易看出原因:(我稍微混淆了这一点)

exec [sys].sp_describe_first_result_set 
N'Update [MAIN].[dbo].[Inventory] Set ExportId = @P1 Where Comp = @P2 and Osite = @P3 and Key = @P4',
N'@P1 numeric(10),@P2 varchar(6),@P3 varchar(6),@P4 int',1

这个和类似的语句每个都需要半秒钟。该实用程序必须使用有关导出的一些信息更新主清单 table,并且 table 被严重触发,因此 sp_describe_first_result_set 必须模拟所有触发器以确定结果 -我可以稍后在跟踪中验证这一点。

问题

我不明白为什么我的代码会调用 sp_describe_first_result_set 更新语句,甚至没有结果集。命令设置看起来没有做任何奇怪的事情:

Dim connection = New ADODB.Connection
connection.ConnectionString = config.AdoConnectionString
connection.CursorLocation = CursorLocationEnum.adUseClient
connection.Open()

cmd = New ADODB.Command
With cmd
  .ActiveConnection = connection
  .CommandType = CommandTypeEnum.adCmdText
  .CommandText = "Update [MAIN].[dbo].[Inventory] " &
                 "Set ExportId = ? " &
                 "Where Comp = ? and Osite = ? and Key = ?"
  .Parameters.Append(NumericParameter(cmd.CreateParameter("ExportId", DataTypeEnum.adNumeric, ParameterDirectionEnum.adParamInput), 10, 0))
  .Parameters.Append(cmd.CreateParameter("Comp", DataTypeEnum.adVarChar, ParameterDirectionEnum.adParamInput, 6))
  .Parameters.Append(cmd.CreateParameter("Osite", DataTypeEnum.adVarChar, ParameterDirectionEnum.adParamInput, 6))
  .Parameters.Append(cmd.CreateParameter("Key", DataTypeEnum.adInteger, ParameterDirectionEnum.adParamInput))
End With

cmd.Parameters("ExportID").Value = lExportId
cmd.Parameters("Comp").Value = sComp
cmd.Parameters("Osite").Value = sOsite
cmd.Parameters("Key").Value = iKey
cmd.Execute()

是否有一些我一直缺少的设置一直 运行 sp_describe_first_result_set?有没有办法阻止它这样做?

出于好奇,与该代码等效的现代代码是否也跟踪执行此操作?

Dim cmd as New SqlCommand( _
  "Update [MAIN].[dbo].[Inventory] Set ExportId = @e Where Comp = @c and Osite = @o and Key = @k", 
  "Data Source=YOUR_SERVER;Initial Catalog=YOUR_DB;User ID=YOUR_USER_EG_sa;Password=YOUR_PASSWORD" _
)
cmd.Connection.Open()
cmd.Parameters.AddWithValue("@e", lExportId)
cmd.Parameters.AddWithValue("@c", sComp)
cmd.Parameters.AddWithValue("@o", sOsite)
cmd.Parameters.AddWithValue("@k", iKey)
cmd.ExecuteNonQuery()

我在这里使用 AddWithValue 是为了 testing/convenience 目的,但您可能应该在产品中避免使用它 because it can cause performance issues with SQLS - 请参阅 link 以获取有关如何正确制作参数的建议

您需要明确说明您不需要记录集。

在 VB6 中,ADODB 命令对象可以根据 Execute() 函数的值是否被分配给任何东西来判断它是否应该 return 一个记录集。

在 VB.NET 中不再这样做,但是 execution options flags 可以作为参数提供给 Execute() 函数。像这样调用命令:

cmd.Parameters("ExportID").Value = lExportId
cmd.Parameters("Comp").Value = sComp
cmd.Parameters("Osite").Value = sOsite
cmd.Parameters("Key").Value = iKey
cmd.Execute(Options:=ExecuteOptionEnum.adExecuteNoRecords)

不会调用sp_describe_first_result_set建立记录集的参数,只会直接执行命令,同理更现代的方法如SqlCommand.ExecuteNonQuery()也会。