将参数添加到SQLCommand,然后稍后添加值

huangapple go评论74阅读模式
英文:

Adding parameters to SQLCommand and adding value later

问题

我看到了关于使用 Parameters.AddParameters.AddWithValue 的不同讨论(一个是显式的,另一个不是),但这不是我的问题。

我正在定义一个命令,将用于对数据库进行多次插入操作。我想做以下类似的事情:

[定义命令]
[添加参数(包括此时未知的batchid)]

[进入循环]
[创建新的batchid]
[设置参数值]
[执行命令]
[下一步]

这意味着我的参数提前清晰地定义,而我在循环内设置它们的值。这段代码如下:

$SqlCmdAdd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmdAdd.CommandType = [System.Data.CommandType]::StoredProcedure
$SqlCmdAdd.CommandText = "AddBatch"
$SqlCmdAdd.Parameters.Add("@RunId", [Data.SQLDBType]::UniqueIdentifier)
$SqlCmdAdd.Parameters.Add("@RunType", [Data.SQLDBType]::NVarChar, 50)
$SqlCmdAdd.Connection = $SqlConnection

在循环内,我认为可以这样做:

# 生成用作BatchID的GUID
$batchID = [guid]::NewGuid()

# 我尝试使用参数名称和它们的数字顺序。都不起作用
$SqlCmdAdd.Parameters["@RunId"].Value = $batchID | Out-Null
$SqlCmdAdd.Parameters["@RunType"].Value = "HDD" | Out-Null
# $SqlCmdAdd.Parameters[0].SqlValue = $batchID | Out-Null
# $SqlCmdAdd.Parameters[1].SqlValue = "HDD" | Out-Null

然而,如果我读取 $SqlCmdAdd.Parameters[0] 和 [1] 的值,我会看到正确的名称和数据类型,但它们的值为空。因此,我将会收到一个错误,指出没有为参数指定值。

有效的方法是:

$SqlCmdAdd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmdAdd.CommandType = [System.Data.CommandType]::StoredProcedure
$SqlCmdAdd.CommandText = "AddBatch"
$SqlCmdAdd.Connection = $SqlConnection

在循环中执行以下操作:

# 添加参数
$SqlCmdAdd.Parameters.AddWithValue("@RunId", $batchID) | Out-Null
$SqlCmdAdd.Parameters.AddWithValue("@RunType", "HDD") | Out-Null
$SqlCmdAdd.ExecuteNonQuery()
$SqlConnection.Close()

# 清除参数集合以供下一次运行使用
$SqlCmdAdd.Parameters.Clear()

让我困扰的是需要在下一次运行之前清除参数集合,然后重新创建它们。虽然这可以运行我的代码,但我有兴趣找出为什么尝试在第一个代码块中设置早期创建的参数的值没有任何效果。

我尝试过搜索并阅读了无数文章。

英文:

I've seen the different discussions of using Parameters.Add vs Parameters.AddWithValue (one is explicit, the other is not), but that isn't my issue.

I'm defining a command, which will be used to do multiple inserts into the database. I figured I'd do something like the following:

[define command]
[add parameters (including a batchid not known at this time)]

[enter loop]
   [create new batchid]
   [set parameter value]
   [execute command]
[next]

This would mean my parameters are neatly defined in advance, and I set their values within the loop. The code for that looks like this:

$SqlCmdAdd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmdAdd.CommandType = [System.Data.CommandType]::StoredProcedure
$SqlCmdAdd.CommandText = "AddBatch"
$SqlCmdAdd.Parameters.Add("@RunId", [Data.SQLDBType]::UniqueIdentifier)
$SqlCmdAdd.Parameters.Add("@RunType", [Data.SQLDBType]::NVarChar, 50)
$SqlCmdAdd.Connection = $SqlConnection

Within the loop I figured I could do something like this:

# Generate GUID to be used as a BatchID
$batchID = [guid]::NewGuid()

# I tried both using the parameter name, as well as their numeric order. Neither worked
$SqlCmdAdd.Parameters["@RunId"].Value = $batchID | Out-Null
$SqlCmdAdd.Parameters["@RunType"].Value = "HDD" | Out-Null
# $SqlCmdAdd.Parameters[0].SqlValue = $batchID | Out-Null
# $SqlCmdAdd.Parameters[1].SqlValue = "HDD" | Out-Null

However, if I read out the values of $SqlCmdAdd.Parameters[0] and [1], I see the proper names and data types, but their values are null. Thus, I'll get an error that no values were specified for the parameters.

What did work was:

$SqlCmdAdd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmdAdd.CommandType = [System.Data.CommandType]::StoredProcedure
$SqlCmdAdd.CommandText = "AddBatch"
$SqlCmdAdd.Connection = $SqlConnection

Within the loop doing this:

# Add parameters
$SqlCmdAdd.Parameters.AddWithValue("@RunId", $batchID) | Out-Null
$SqlCmdAdd.Parameters.AddWithValue("@RunType", "HDD") | Out-Null
$SqlCmdAdd.ExecuteNonQuery()
$SqlConnection.Close()

# Clear parameter collection for next run
$SqlCmdAdd.Parameters.Clear()

What irritates me about this is the need to clear the parameter collection for the next run, and then recreating them. While that runs my code, I'm interested in finding out why attempting to set the value of the earlier created parameters in the first code block doesn't have any effect.

I tried googling and read countless articles.

答案1

得分: 7

这是因为在赋值之前将变量传递给 Out-Null,所以会发生这种情况。因此,

$SqlCmdAdd.Parameters["@RunId"].Value = $batchID | Out-Null

将首先将 $batchID 传递给 Out-Null,并将结果 $null 分配给 .Value

至于修复方法,只需删除 Out-Null,像这样:

$SqlCmdAdd.Parameters["@RunId"].Value = $batchID
英文:

This happens, as piping the variable to Out-Null happens before assignment. Thus,

$SqlCmdAdd.Parameters["@RunId"].Value = $batchID | Out-Null

Will first pass $batchID to Out-Null, and the result - $null - is assigned into .Value.

As for a fix, just remove Out-Null like so,

$SqlCmdAdd.Parameters["@RunId"].Value = $batchID

huangapple
  • 本文由 发表于 2020年1月3日 20:38:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/59578788.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定