Почему Powershell думает, что я пытаюсь вернуть объект [], а не DataTable?

у меня есть следующая функция PS:

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

Я получаю следующую ошибку:

не удается преобразовать " System.Object [] система "значение типа".Объект[]" для системы типа ".Данные.объект DataTable."

почему Powershell думает, что я хочу вернуть массив object [], когда это очевидно что переменная $dt является DataTable?

EDIT:

Я дважды проверил, и $dt содержит данные. Например, количество строк.Количество-1, которое ожидается.

4 ответов


Я не знаю о других проблемах, которые люди поднимают, но я могу придумать две возможные причины, почему вы возвращаетесь Object[].

  1. возможно, у вас есть некаптированный вывод где-то еще в функции. В твоем случае, Fill возвращает int. Попробуйте добавить это в конец вызовов функций:

    | Out-Null
    

    Е. Г.,

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

    если какой-либо оператор возвращает значение, и вы его не фиксируете, вывод будет включен в возвращаемое значение, и поскольку в этот момент у вас будет несколько возвращаемых значений, PowerShell запихнет их все в массив.

  2. другая возможность, которая преобразует PowerShell возвращены коллекций всякие в Object[]s. Используйте , оператор для возврата значения unmangled:

    return , $dt
    

    на , создает массив, содержащий только следующее значение. Насколько я могу догадаться, это заставляет PowerShell автоматически разверните внешний массив и оставьте значение в покое, так как фактическое возвращаемое значение теперь является массивом, который содержит только одно значение.

    на return на самом деле является необязательным, так как незахваченные значения включены в возвращаемое значение.

    только вчера столкнулся с этим сам. Я не могу ни за что на свете понять, почему кто-то думает, что тихо превращается в Object[] - это полезно.


У вас есть несколько вопросов в том, что вы опубликовали. Поскольку вы явно создаете объект DataTable с помощью New-Object System.Data.DataTable, нет причин также принуждать его к типу DataTable с [System.Data.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

и это сработало просто отлично. Я подозреваю, что бит, который вызывает вашу проблему, вероятно, в бит, который вы исключили для краткости. Ярлыки редко бывают, и вы редко получаете точные ответы от частичных данных.


способствующим фактором является то, что вы фактически не вызываете методы open и close, а ссылаетесь на них вместо этого. PowerShell выводит ссылку на эти методы, а также datatable (который, я полагаю, фактически не заполняется из-за того, что соединение не открыто).

вам нужно включить круглые скобки в методы open/close следующим образом:

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

вам также нужно остерегаться методов, которые возвращают значения (.Методы Add () печально для этого), что вы не потребляете, назначая переменной или конвейеру out-null.


вам просто нужно аннулировать все ваши команды dot, которые не назначены переменным

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
}

что касается вашего вопроса Почему? ... Читайте блог кита Хилла:как вернуть работу функции powershell