Powershell 和 SQL 参数。 如果为空字符串,则传递 DBNull

发布于 2024-07-23 05:29:28 字数 671 浏览 6 评论 0原文

我得到了这个参数:

$objDbCmd.Parameters.Add("@telephone", [System.Data.SqlDbType]::VarChar, 18) | Out-Null;
$objDbCmd.Parameters["@telephone"].Value = $objUser.Telephone;

其中字符串 $objUser.Telephone 可以为空。 如果它是空的,如何将其转换为[DBNull]::Value

我尝试过:

if ([string]:IsNullOrEmpty($objUser.Telephone)) { $objUser.Telephone = [DBNull]::Value };

但这给了我错误:

使用“0”个参数调用“ExecuteNonQuery”时出现异常:“无法将参数值从 ResultPropertyValueCollection 转换为字符串。”

如果我将其转换为字符串,它会插入一个空字符串 "",而不是 DBNull

如何才能做到这一点?

谢谢。

I got this parameter:

$objDbCmd.Parameters.Add("@telephone", [System.Data.SqlDbType]::VarChar, 18) | Out-Null;
$objDbCmd.Parameters["@telephone"].Value = $objUser.Telephone;

Where the string $objUser.Telephone can be empty. If it's empty, how can I convert it to [DBNull]::Value?

I tried:

if ([string]:IsNullOrEmpty($objUser.Telephone)) { $objUser.Telephone = [DBNull]::Value };

But that gives me the error:

Exception calling "ExecuteNonQuery" with "0" argument(s): "Failed to convert parameter value from a ResultPropertyValueCollection to a String."

And if I convert it to a string, it inserts an empty string "", and not DBNull.

How can this be accomplished?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

两相知 2024-07-30 05:29:28

在 PowerShell 中,您可以将 null/空字符串视为布尔值。

$x = $null
if ($x) { 'this wont print' }

$x = ""
if ($x) { 'this wont print' }

$x = "blah"
if ($x) { 'this will' }

所以......话虽如此,你可以这样做:

$Parameter.Value = $(if ($x) { $x } else { [DBNull]::Value })

但我宁愿将其包装在一个函数中,例如:

function CatchNull([String]$x) {
   if ($x) { $x } else { [DBNull]::Value }
}

In PowerShell, you can treat null/empty strings as a boolean.

$x = $null
if ($x) { 'this wont print' }

$x = ""
if ($x) { 'this wont print' }

$x = "blah"
if ($x) { 'this will' }

So.... having said that you can do:

$Parameter.Value = $(if ($x) { $x } else { [DBNull]::Value })

But I'd much rather wrap this up in a function like:

function CatchNull([String]$x) {
   if ($x) { $x } else { [DBNull]::Value }
}
魄砕の薆 2024-07-30 05:29:28

我不知道 powershell,但在 C# 中我会做这样的事情:

if ([string]::IsNullOrEmpty($objUser.Telephone))
{
 $objDbCmd.Parameters["@telephone"].Value = [DBNull]::Value;
}
else
{
 $objDbCmd.Parameters["@telephone"].Value = $objUser.Telephone;
}

I don't know about powershell, but in C# I would do something like this:

if ([string]::IsNullOrEmpty($objUser.Telephone))
{
 $objDbCmd.Parameters["@telephone"].Value = [DBNull]::Value;
}
else
{
 $objDbCmd.Parameters["@telephone"].Value = $objUser.Telephone;
}
已下线请稍等 2024-07-30 05:29:28

始终在数据库值末尾附加 +"" ...

$command.Parameters["@EmployeeType"].Value= $ADResult.EmployeeType + ""

Always append +"" at the end of db values...

$command.Parameters["@EmployeeType"].Value= $ADResult.EmployeeType + ""

谜兔 2024-07-30 05:29:28

许多年后,让我澄清一下:

Josh 的回答展示了测试字符串是否为空的有用简化(依赖于 PowerShell 的 隐式到布尔转换[1]),但它与Tommy(OP)的问题无关。

相反,错误消息

“无法将参数值从 ResultPropertyValueCollection 转换为字符串。”

暗示这是导致问题的-null情况,因为$objDbCmd.Parameters["@telephone"].Value期望字符串值或[DBNull]::Value,而$objUser.Telephone的类型为[ResultPropertyValueCollection] ,即值的集合

因此,在非空情况下,必须分配一个字符串值,该值必须从集合中派生; 一种选择是获取第一个集合元素的值,另一种选择是使用分隔符将所有值连接起来形成单个字符串,例如使用 [string]::Join('; ', $objUser.Telephone) 或者,如果使用空格连接元素是可以接受的(对于多个电话号码不是一个好主意),只需使用 "$($objUser. Telephone)".[2]

通过 [string]:IsNullOrEmpty() 检测空集合实际上有效,尽管类型不匹配,因为 PowerShell 隐式地将值传递给 [string] 类型化方法参数时对集合进行字符串化。[2]

同样,使用隐式布尔转换可以按预期工作集合也是如此:空集合的计算结果为 $false,非空集合的计算结果为 $true(只要至少有两个元素或唯一的元素)本身将被视为$true[1]

因此,一种解决方案是使用第一个电话号码条目:

$objDbCmd.Parameters["@telephone"].Value = if ($objUser.Telephone) {
    $objUser.Telephone[0].ToString()  # use first entry
  } else {
    [DBNull]::Value
  }

注意:如果$objUser.Telephone[0]直接返回一个[string],可以省略.ToString()调用。

PowerShell v7+ 您也可以通过三元条件缩短语句:

$objDbCmd.Parameters["@telephone"].Value =
  $objUser.Telephone ? $objUser.Telephone[0].ToString() : [DBNull]::Value

[1] 有关 PowerShell 自动布尔转换的全面摘要,请参阅 这个答案

[2] 当隐式将集合转换为字符串时,PowerShell 会加入字符串化的字符串默认情况下以单个空格作为分隔符的集合元素; 您可以使用自动 $OFS 变量覆盖分隔符,但在实践中很少这样做; 例如,数组 'foo', 'bar' 转换为 'foo bar'; 请注意,当您显式调用集合的 .ToString() 方法时,此转换应用,但它确实适用于可扩展(插值)字符串内部,例如,“$array”

Many years later, let me clarify:

Josh's answer shows a helpful simplification for testing strings for emptiness (relying on PowerShell's implicit to-Boolean conversion[1]), but it is unrelated to Tommy's (the OP's) problem.

Instead, the error message

"Failed to convert parameter value from a ResultPropertyValueCollection to a String."

implies that it is the non-null case that caused the problem, because $objDbCmd.Parameters["@telephone"].Value expects either a string value or [DBNull]::Value, whereas $objUser.Telephone is of type [ResultPropertyValueCollection], i.e. a collection of values.

Thus, in the non-null case, a string value must be assigned, which must be derived from the collection; one option is to take the first collection element's value, another would be to join all values with a separator to form a single string, using, e.g., [string]::Join(';', $objUser.Telephone) or, if joining the elements with spaces is acceptable (not a good idea with multiple phone numbers), simply with "$($objUser.Telephone)".[2]

Detecting an empty collection via [string]:IsNullOrEmpty() actually worked, despite the type mismatch, due to how PowerShell implicitly stringifies collections when passing a value to a [string] typed method parameter.[2]

Similarly, using implicit to-Boolean conversion works as expected with collections too: an empty collection evaluates to $false, a non-empty one to $true (as long as there are either at least two elements or the only element by itself would be considered $true[1])

Therefore, one solution is to use the first telephone number entry:

$objDbCmd.Parameters["@telephone"].Value = if ($objUser.Telephone) {
    $objUser.Telephone[0].ToString()  # use first entry
  } else {
    [DBNull]::Value
  }

Note: If $objUser.Telephone[0] directly returns a [string], you can omit the .ToString() call.

In PowerShell v7+ you can alternatively shorten the statement via a ternary conditional:

$objDbCmd.Parameters["@telephone"].Value =
  $objUser.Telephone ? $objUser.Telephone[0].ToString() : [DBNull]::Value

[1] For a comprehensive summary of PowerShell's automatic to-Boolean conversions, see the bottom section of this answer.

[2] When implicitly converting a collection to a string, PowerShell joins the stringified elements of a collection with a single space as the separator by default; you can override the separator with the automatic $OFS variable, but that is rarely done in practice; e.g., array 'foo', 'bar' is converted to 'foo bar'; note that this conversion does not apply when you call the collection's .ToString() method explicitly, but it does apply inside expandable (interpolating) strings, e.g., "$array".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文