我都快疯了。我有一个来自多个脚本的库,其中包含以下函数:
function lib_open_dataset([string] $sql) {
$ds = new-object "System.Data.DataSet"
$da = new-object "System.Data.SqlClient.SqlDataAdapter" ($sql, $_conn_string)
$record_count = $da.Fill($ds)
return $ds
}
这几乎在任何地方都被称为,它工作得很好,除了我通常必须这样做:
$ds = lib_open_dataset($some_sql)
$table = $ds.Tables[0]
foreach ($row in $table.Rows) {
# etc
}
因此,我创建了一个新的简单包装器函数,以避免取消引用第一个表的额外步骤:
function lib_open_table([string] $sql) {
$ds = lib_open_dataset $sql
return $ds.Tables[0]
}
问题是,由于某种原因,从这里返回的是表的行集合,而不是表本身。这会导致如上编写的foreach
行循环失败,并显示"Cannot index into a null array“。异常。经过多次尝试和错误,我发现这是可行的:
foreach ($row in $table) {
# etc
}
注意$table.Rows
和foreach
语句中的$table
之间的区别。此works。因为$table
实际上指向行集合。如果语句
return $ds.Tables[0]
假设是正确的,为什么函数返回表对象的子集而不是表本身?
我猜Powershell函数的工作方式中有一些明显的原因,但我不知道是什么原因。
发布于 2009-12-17 07:06:13
您可以使用逗号运算符将行集合包装在数组中,以便在展开数组时以原始的行集合结束,例如:
function lib_open_table([string] $sql) {
$ds = lib_open_dataset $sql
return ,$ds.Tables[0]
}
从本质上讲,你不能阻止PowerShell展开数组/集合。您可以做的最好的工作是通过将数组/集合包装在另一个单元素数组中来解决这种行为。
发布于 2009-12-19 06:05:09
PowerShell特殊情况-在内部使用DataTable。它没有实现任何常见的可疑接口,如ICollection、IList或IEnumerable,这些接口通常会触发展开。您可以使用以下命令对此进行深入研究:
PS> $dt = new-object data.datatable
PS> $dt -is [collections.ienumerable]
False
然而:
PS> $e = [management.automation.languageprimitives]::GetEnumerator($dt)
PS> $e.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
False False RBTreeEnumerator System.ValueType
-Oisin
发布于 2011-05-19 23:39:17
需要注意的两件事a)在返回的对象前面加上逗号b)在填充适配器时,确保将结果赋值给(可处理的)变量或执行Out-Null
我没有执行Out-Null,甚至在前面加上逗号,我也不断地从查询中得到一个集合(item 0= number of rows from the query,item1= the datatable),这让我有点抓狂,直到我选择了Out-null参数。
非常奇怪的IMHO,因为我特别要求返回datatable,但一直在取回集合,即使前面有",“
function Oracleconnection
{
process
{
trap
{
Write-Host "error occured on oracle connection"
Write-Host $_
continue
}
[System.Reflection.Assembly]::LoadWithPartialName(“System.Data.OracleClient”) | out-null
$connection = new-object system.data.oracleclient.oracleconnection( `
"Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=myhost.host)(PORT=1800)) `
(CONNECT_DATA=(SERVICE_NAME=myservicename)));User Id=myid;Password=mypassword;");
$query = "SELECT country, asset FROM table "
$set = new-object system.data.dataset
$adapter = new-object system.data.oracleclient.oracledataadapter ($query, $connection)
$adapter.Fill($set) | Out-Null
$table = new-object system.data.datatable
$table = $set.Tables[0]
return ,$table
}
}
(来自Keith答案的概念!)
https://stackoverflow.com/questions/1918190
复制相似问题