我有以下PS功能:
function GetBuildData {
[System.Data.SqlClient.SqlConnection] $conn = New-Object System.Data.SqlClient.SqlConnection
[System.Data.SqlClient.SqlCommand] $cmd = New-Object System.Data.SqlClient.SqlCommand
[System.Data.SqlClient.SqlDataAdapter] $adapter = New-Object System.Data.SqlClient.SqlDataAdapter
[System.Data.DataTable] $dt = New-Object System.Data.DataTable
try {
[string] $connStr = "myConnectionString"
$conn.ConnectionString = $connStr
$cmd.Connection = $conn
$cmd.CommandText = "SELECT * FROM TestTable"
$conn.Open
$adapter.SelectCommand = $cmd
$adapter.Fill($dt)
$conn.Close
}
catch [system.exception]
{
Write-Host $_
}
finally {
$adapter.Dispose
$cmd.Dispose
$conn.Dispose
}
return $dt
}
为简洁起见,删除了大部分功能。我遇到的问题是当我这样调用函数时:
[System.Data.DataTable] $buildData = GetBuildData
我收到以下错误:
无法转换“System.Object []”类型的“System.Object []”值 输入“System.Data.DataTable”。
为什么Powershell认为我很想在$ dt变量是DataTable时返回一个object []数组?
编辑:
我已经仔细检查了,$dt
确实包含了数据。例如,Rows.Count的数量是1,这是预期的。
答案 0 :(得分:15)
我不知道人们提出的其他问题,但我可以想到你回到Object[]
的两个可能原因。
可能是您在函数中的其他位置有未捕获的输出。在您的情况下,Fill
会返回int
。尝试将此添加到函数调用的末尾:
| Out-Null
如,
$adapter.Fill($dt) | Out-Null
如果任何语句返回一个值并且您没有捕获它,则输出将包含在您的返回值中,并且由于此时您将有多个返回值,PowerShell会将它们全部填充到数组中。 / p>
另一种可能性是PowerShell将所有类型的返回集合转换为Object[]
s。使用,
运算符返回未编码的值:
return , $dt
,
创建一个仅包含后面值的数组。就像我猜的那样,这会导致PowerShell自动展开最外面的数组并保留值,因为实际返回值现在是一个只包含单个值的数组。
return
实际上是可选的,因为未捕获的值包含在返回值中。
昨天我自己碰到了这个。我不能为我的生活弄清楚为什么有人会认为默默地转换为Object[]
是有用的。
答案 1 :(得分:0)
您发布的内容确实存在一些问题。由于您使用New-Object System.Data.DataTable
显式创建了一个DataTable对象,因此没有理由使用[System.Data.DataTable]
将其强制转换为DataTable类型。调用函数时也是如此。您正在返回一个DataTable对象,因此您将返回该对象。此外,如果您确实要指定变量类型,则类型标识符和变量名称之间不应有空格。无论如何,这些问题不会导致您看到的行为。我运行了这段代码:
function GetBuildData {
$dt = New-Object System.Data.DataTable
$column1 = New-Object system.Data.DataColumn 'Col1'
$column2 = New-Object system.Data.DataColumn 'Col2'
$dt.columns.add($column1)
$dt.columns.add($column2)
$row = $dt.NewRow()
$row.col1 = '1'
$row.col2 = '2'
$dt.rows.add($row)
return $dt
}
$buildData = GetBuildData
$buildData
Col1 Col2
---- ----
1 2
它运作得很好。我怀疑造成你问题的那个位可能是你为了简洁而被排除在外的位。快捷方式很少,您很少从部分数据中获得准确的答案。
答案 2 :(得分:0)
一个促成因素是你实际上并没有调用open和close方法,而是引用它们。 PowerShell正在输出对这些方法以及数据表的引用(由于连接未打开,我想象的实际上并没有填充)。
您需要在开/关方法中包括括号,如下所示:
$conn.Open()
...
$conn.Close()
您还需要注意返回值的方法(.Add()方法因此而臭名昭着),您不会通过分配给变量或管道输出为null来消耗它。
答案 3 :(得分:0)
您必须清空所有未分配给变量的点命令
function GetBuildData {
[System.Data.SqlClient.SqlConnection] $conn = New-Object System.Data.SqlClient.SqlConnection
[System.Data.SqlClient.SqlCommand] $cmd = New-Object System.Data.SqlClient.SqlCommand
[System.Data.SqlClient.SqlDataAdapter] $adapter = New-Object System.Data.SqlClient.SqlDataAdapter
[System.Data.DataTable] $dt = New-Object System.Data.DataTable
try {
[string] $connStr = "myConnectionString"
$conn.ConnectionString = $connStr
$cmd.Connection = $conn
$cmd.CommandText = "SELECT * FROM TestTable"
[void]$conn.Open
$adapter.SelectCommand = $cmd
$adapter.Fill($dt)
[void]$conn.Close
}
catch [system.exception]
{
Write-Host $_
}
finally {
[void]$adapter.Dispose
[void]$cmd.Dispose
[void]$conn.Dispose
}
$dt
}
关于你的问题为什么? ...阅读Keith Hill的博客:how does return work powershell functions