2009-12-16 33 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 
    } 
}