Странное поведение в функции 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, это вызывает это, очевидно, но я не могу выяснить что.

20
задан kprobst 16 December 2009 в 22:15
поделиться

2 ответа

Вы можете использовать оператор запятой, чтобы обернуть коллекцию строк в массив, чтобы при развертывании массива вы получали исходную коллекцию строк, например:

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

По сути, вы не можете предотвратить PowerShell от развертывания массивов / коллекций. Лучшее, что вы можете сделать, - это обойти такое поведение, заключив массив / коллекцию в другой одноэлементный массив.

23
ответ дан 29 November 2019 в 23:57
поделиться

PowerShell - особые случаи для внутреннего DataTable. Он не реализует ни один из обычных подозрительных интерфейсов, таких как 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

12
ответ дан 29 November 2019 в 23:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: