2012-12-20 71 views
8

我有以下的PS功能:爲什麼Powershell認爲我試圖返回一個對象[]而不是DataTable?

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

我得到以下錯誤:

Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Data.DataTable".

爲什麼Powershell的認爲,我想返回的對象[]數組當很明顯$ dt變量是一個DataTable?

編輯:

我有雙重檢查,並$dt確實包含數據。例如,Rows.Count的數量是1,這是預期的。

+0

發生什麼錯誤?錯誤信息應該提供行和字符號。我假設它發生在這裏:$ adapter.Fill($ dt)?? – D3vtr0n

+0

你有沒有嘗試','操作符jpmc26的答案建議?我遇到了這個問題,那就是解決方案。 –

+0

有沒有解決你的問題的答案?如果不是,可否添加一些關於他們爲什麼不工作的更多信息? – jpmc26

回答

13

我不知道人們正在提出的其他問題,但我可以想到兩個可能的原因,你爲什麼要回Object[]

  1. 可能是因爲您在函數的其他位置有未捕獲的輸出。在你的情況下,Fill返回int。嘗試將此添加到函數調用的最後:

    | Out-Null 
    

    例如,,

    $adapter.Fill($dt) | Out-Null 
    

    如果任何語句返回一個值,你沒有捕捉它,輸出將被包含在你的返回值,因爲你在這一點上有多個返回值,PowerShell的將他們的東西全部成陣列。

  2. 另一種可能性是PowerShell將各種返回的集合轉換爲Object[] s。使用操作者,返回未重整值:

    return , $dt 
    

    ,創建僅包含下面的值的數組。據我所知,這會導致PowerShell自動展開最外層的數組,並保留該值,因爲實際返回值現在是隻包含單個值的數組。

    return實際上是可選的,因爲未捕獲的值包含在返回值中。

    昨天自己剛剛碰到這個。我不能爲我的生活弄清楚爲什麼有人會默默地認爲轉換爲Object[]是有用的。

+2

這就是答案!現在我可以從我的頭部造成的傷害中修復牆。同上「我不能爲了我的生活弄清楚爲什麼有人會默默地轉換爲Object []'是有用的。」也許微軟與牆壁維修承包商達成了回扣協議? –

+0

順便說一句,我看到,這可以結合**返回**,即'返回,$ dt'也適用,如果你想返回** $ dt **未轉換並在那裏結束功能。 –

+0

還有一點需要注意的是,即使您不使用** return **關鍵字,轉換也會發生。如果單獨計算最後一個表達式爲** $ dt **,則該函數將返回一個對象數組。 –

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 

它工作得很好。我懷疑造成你的問題的那一點可能是你爲了簡潔而排除的那一點。快捷鍵很少,你很少從部分數據得到準確的答案。

+0

我已經添加了整個函數,以防萬一,爲什麼它不能爲我工作提供任何線索。 –

+0

在函數中,如果你有輸出$ dt的內容,它是否有數據?如果你在函數中做$ dt.GetType(),它認爲$ dt是什麼? – EBGreen

+1

我也建議在創建變量時刪除所有這些類型標識符。他們是不必要的,可能會導致這個問題,儘管我不這麼認爲。 – EBGreen

0

一個促成因素是,您實際上並沒有調用open和close方法,而是引用它們。 PowerShell正在輸出對這些方法的引用以及數據表(我想可能由於連接未打開而實際上未被填充)。

您需要包括在打開/關閉的方法是這樣的括號:

$conn.Open() 
... 
$conn.Close() 

您還需要提防其返回值(。新增()方法是臭名昭著的這個)方法,您」不要通過將變量或管道分配給out-null來消費。

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

相關問題