2012-12-20 7 views
8

Mam następującą funkcję PS:Dlaczego aplikacja Powershell uważa, że ​​próbuję zwrócić obiekt [] zamiast elementu 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 
} 

Większość funkcji została usunięta dla zwięzłości. Mam problem jest, kiedy wywołać funkcję tak:

[System.Data.DataTable] $buildData = GetBuildData

pojawia się następujący błąd:

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

Dlaczego PowerShell myśleć, że jestem chcąc obiektu [] tablicy zwróconej kiedy jest oczywiste, że zmienną $ dt jest DataTable?

EDIT:

mam dwukrotnie sprawdzane i $dt nie zawierają danych. Na przykład liczba Rows.Count wynosi 1, która jest oczekiwana.

+0

w jakiej linii pojawia się błąd? komunikat o błędzie powinien zawierać wiersz i numer znaku. Zakładam, że to się dzieje tutaj: $ adapter.Fill ($ dt)? – D3vtr0n

+0

Czy kiedykolwiek próbowałeś użyć operatora ',' jak sugeruje odpowiedź jpmc26? Wpadłem na ten problem i to było rozwiązanie. –

+0

Czy któraś z odpowiedzi rozwiązała Twój problem? Jeśli nie, czy mógłbyś dodać więcej informacji o tym, dlaczego nie działały? – jpmc26

Odpowiedz

13

Nie wiem o innych problemach, które ludzie wywołują, ale mogę wymyślić dwa możliwe powody, dla których wracasz do wersji Object[].

  1. Możliwe, że masz niezakaprtowane wyjście w innym miejscu tej funkcji. W twoim przypadku Fill zwraca int. Spróbuj dodać to na końcu wywołań funkcji:

    | Out-Null 
    

    E.g.,

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

    Jeśli jakakolwiek instrukcja zwraca wartość i nie masz uchwycenie go, wyjście zostaną uwzględnione w wartości zwracanej, a ponieważ będziesz mieć wiele wartości zwracanych w tym punkcie, PowerShell będzie je wszystkie rzeczy do tablicy.

  2. Inną możliwością jest to, że PowerShell konwertuje zwracane kolekcje różnego rodzaju w Object[] s. Za pomocą operatora , zwraca wartość unmangled:

    return , $dt 
    

    , tworzy tablicę zawierającą tylko wartość, następuje. Tak blisko, jak się domyślam, powoduje to, że PowerShell automatycznie odwija ​​najbardziej zewnętrzną tablicę i pozostawia samą wartość, ponieważ faktyczna wartość zwracana jest teraz tablicą, która zawiera tylko jedną wartość.

    Opcja return jest opcjonalna, ponieważ wartości niewykryte są uwzględniane w wartości zwracanej.

    Właśnie wczoraj wpadłem na to. Nie mogę do końca życia zrozumieć, dlaczego ktokolwiek mógłby pomyśleć, że konwersja w trybie cichym jest użyteczna.

+2

Oto odpowiedź! Teraz mogę naprawić ścianę od obrażeń spowodowanych przez moją głowę. Ditto na temat "Nie mogę do końca życia dowiedzieć się, dlaczego ktokolwiek mógłby pomyśleć, cicho konwersji do' Object [] 'jest przydatne." Może Microsoft ma umowę odrzuceń z wykonawcą robót remontowych? –

+0

BTW, widzę, że można to połączyć z ** return **, tj. 'Return, $ dt' działa również, jeśli chcesz zwrócić ** $ dt ** unconverted i zakończyć funkcję właśnie tam. –

+0

Jeszcze jedna uwaga, którą chciałbym dodać, to to, że konwersja ma miejsce, nawet jeśli nie używasz słowa kluczowego ** return **. Jeśli ostatnie wyliczone wyrażenie ma wartość ** $ dt **, funkcja zwraca tablicę obiektów. –

0

Masz kilka problemów z tym, co napisałeś. Ponieważ jawnie tworzysz obiekt DataTable z New-Object System.Data.DataTable, nie ma powodu, aby go przymuszać do typu DataTable z [System.Data.DataTable]. To samo dotyczy sytuacji, gdy wywołujesz funkcję. Zwracasz obiekt DataTable, więc to właśnie otrzymasz. Również jeśli chcesz określić typ zmiennej, nie powinno być spacji między identyfikatorem typu a nazwą zmiennej. Bez względu na to, problemy te nie spowodują zachowań, które widzisz. Uruchomiłem ten kod:

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 

Wszystko działało dobrze. Podejrzewam, że bit, który powoduje twój problem, prawdopodobnie jest w tym kawałku, który wykluczyłeś dla zwięzłości. Skróty rzadko są i rzadko można uzyskać dokładne odpowiedzi z częściowych danych.

+0

Dodałem całą funkcję, na wszelki wypadek, która daje wskazówki, dlaczego nie działa dla mnie. –

+0

W funkcji, jeśli masz na wyjściu zawartość $ dt, czy ma w niej dane? Jeśli wykonujesz funkcję $ dt.GetType() w funkcji, co ona myśli, że $ dt jest? – EBGreen

+1

Proponuję również pozbyć się wszystkich tych identyfikatorów podczas tworzenia zmiennych. Są niepotrzebne i mogą być przyczyną problemu, chociaż nie sądzę. – EBGreen

0

Przyczyniającym się czynnikiem jest to, że nie wywołuje się metod otwierania i zamykania, ale odwołuje się do nich. PowerShell wyprowadza odwołanie do tych metod, jak również do datatable (które, jak sobie wyobrażam, nie jest faktycznie zapełnione ze względu na fakt, że połączenie nie jest otwarte).

Musisz zawierać nawiasy dotyczące otwierania/zamykania metodami tak:

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

Należy również wystrzegać się metodami, które zwracają wartości (.Add() metody są notorycznie to), że” nie zużywają się przez przypisanie do zmiennej lub orurowania do out-null.

0

Po prostu trzeba unieważnić wszystkie swoje polecenia kropki, które nie są przypisane do zmiennych

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 
} 

Co do Twojego pytania Dlaczego? ... Przeczytaj blog Keitha Hill'a: how does return work powershell functions

Powiązane problemy