Это сводит меня с ума. У меня есть библиотека, которую я получаю из нескольких сценариев, который содержит следующую функцию:
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, это вызывает это, очевидно, но я не могу выяснить что.
Вы можете использовать оператор запятой, чтобы обернуть коллекцию строк в массив, чтобы при развертывании массива вы получали исходную коллекцию строк, например:
function lib_open_table([string] $sql) {
$ds = lib_open_dataset $sql
return ,$ds.Tables[0]
}
По сути, вы не можете предотвратить PowerShell от развертывания массивов / коллекций. Лучшее, что вы можете сделать, - это обойти такое поведение, заключив массив / коллекцию в другой одноэлементный массив.
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