2009-12-16 29 views
18

这让我疯狂。我有多个脚本库我源,其中包含以下功能:返回DataSet/DataTable的PowerShell函数的奇怪行为

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行循环失败,并显示“无法索引到空数组中”。例外。多试错后,我想通了,这个工程:

foreach ($row in $table) { 
    # etc 
} 

注意区别$table.Rows,只是$table之间的foreach声明。这作品。因为$table实际上指向了行集合。如果声明

return $ds.Tables[0] 

被认为是正确的,为什么函数返回表对象的子集合而不是表本身?

我猜有什么东西在路上PowerShell函数的工作,这显然导致此,但我想不出什么。

回答

21

您可以用逗号来包装rows集合在一个数组,这样当阵列展开你风与原始行集合例如:

function lib_open_table([string] $sql) { 
    $ds = lib_open_dataset $sql  
    return ,$ds.Tables[0] 
} 

基本上你不能阻止PowerShell与展开数组/集合。你能做的最好的解决方法是通过在另一个包装的阵列/收藏,单个元素数组的行为。

+0

真棒,那工作。这很奇怪,但它的工作:) 非常感谢基思。 – kprobst 2009-12-16 23:26:11

+0

我不明白的是数组展开的地方。为什么只是Rows集合,为什么不是其他属性?为什么不列属性? – stej 2009-12-17 05:48:52

+0

我不是数据集大师,但我不知道是否返回的数据表是TypedTableBase 这是可枚举的T是T是DataRow。 – 2009-12-17 16:27:44

12

PowerShell的特殊情况下,内部的数据表。它没有实现任何常规疑似接口一样的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

+0

谢谢Oisin,我认为这说明了发生了什么。我想知道的是_why_ PS是否在做这件事? – kprobst 2009-12-22 20:11:11

4

哦,是的,我一直是这样一个struggeling太多,直到我得到这个职位.. (tnxs Keith!),你需要确实专注于

两件事情 一)在前面加上逗号确实 B)当你填写你的适配器,确保无论结果分配给(disposalble)可变您返回的对象或做一个外空

我没做外空,甚至有一个前置的逗号,我一直得到一个回(项0 =从查询的行数,物品1 =数据表) 开车我有点疯狂,直到我选择Out-null参数。

非常怪异恕我直言,我要问具体返回的数据表,但一直得到收集回来,甚至与“”在前面

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 
    } 
}