2009-12-16 22 views
18

Esto me está volviendo loco. Tengo una fuente de la biblioteca I a partir de varias secuencias de comandos, que contiene la siguiente función:Comportamiento extraño en la función PowerShell que devuelve DataSet/DataTable

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 
} 

Esto se conoce prácticamente en todas partes y funciona muy bien, excepto que normalmente tienen que hacer esto:

$ds = lib_open_dataset($some_sql) 
$table = $ds.Tables[0] 
foreach ($row in $table.Rows) { 
    # etc 
} 

así que creé una nueva función simple envoltorio para evitar el paso adicional de eliminación de referencias a la primera tabla:

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

el problema es que lo que está siendo devuelto de aquí es el Recopilación de filas de la tabla por algún motivo, no tabla sí mismo. Esto hace que el bucle de fila foreach escrito como arriba falle con un "No se puede indexar en una matriz nula". excepción. Después de mucho ensayo y error me di cuenta de que esto funciona:

foreach ($row in $table) { 
    # etc 
} 

Nota la diferencia entre $table.Rows y justo $table en la declaración foreach. Este funciona. Porque $table en realidad apunta a la colección Filas. Si la declaración

return $ds.Tables[0] 

supuestamente es correcta, ¿por qué la función que devuelve una colección secundario del objeto de tabla en lugar de la propia tabla?

Supongo que hay algo en el funcionamiento de las funciones de Powershell que está causando esto obviamente, pero no puedo entender qué.

Respuesta

21

Puede utilizar el operador coma para envolver la colección de filas en una matriz de modo que cuando se desenrolla la matriz que terminan con la colección de filas original, por ejemplo:

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

Esencialmente no se puede prevenir PowerShell desde desenrollar matrices/colecciones. Lo mejor que puedes hacer es solucionar ese comportamiento envolviendo la matriz/colección dentro de otra matriz de un solo elemento.

+0

impresionante, que funcionó. Es extraño, pero funcionó :) Muchas gracias Keith. – kprobst

+0

Lo que no entiendo es dónde se desenrolla la matriz. Y por qué solo la colección Rows, ¿por qué no otra propiedad? ¿Por qué no, por ejemplo? Propiedad Columnas? – stej

+0

No soy un gurú de DataSet pero me pregunto si la tabla de datos devuelta es de tipo TypedTableBase que es enumerable sobre T si T es DataRow. –

12

PowerShell casos especiales el DataTable internamente. No implementa ninguna de las interfaces habituales sospechosas como ICollection, IList o IEnumerable que normalmente desencadenan el desenrollado. Usted puede cavar en esto un poco con:

PS> $dt = new-object data.datatable 
PS> $dt -is [collections.ienumerable] 
False 

embargo:

PS> $e = [management.automation.languageprimitives]::GetEnumerator($dt) 
PS> $e.gettype() 

IsPublic IsSerial Name          BaseType 
-------- -------- ----          -------- 
False False RBTreeEnumerator       System.ValueType 

-Oisin

+0

Gracias Oisin, creo que esto aclara lo que está pasando. Lo que me pregunto es ¿por qué PS está haciendo esto? – kprobst

4

Oh, sí, he estado struggeling con éste también hasta que llegué a este post .. (¡tnxs Keith!)

2 cosas que hay que centrarse en el hecho a) anteponer el objeto devuelto con la coma de hecho b) cuando se está llenando su adaptador, asegúrese de que sea asignar el resultado a un (disposalble) Variable o hacer un Out-Null

que no hice el Out-Null e incluso con una coma antepuesta, seguí recibiendo una colección posterior (punto 0 = número de filas de la consulta, elemento1 = la tabla de datos) Drove estoy un poco loco hasta que elegí el parámetro Out-null.

mi humilde opinión muy raro, ya que estoy pidiendo específicamente para devolver la tabla de datos, pero mantuvo a la compra al volver, incluso con el "" delante

function Oracleconnection 
{ 
    process 
    { 
    trap 
    { 
     Write-Host "error occured on oracle connection" 
     Write-Host $_ 
     continue 
    } 
    [System.Reflection.Assembly]::LoadWithPartialName(“System.Data.OracleClient”) | out-null 
    $connection = new-object system.data.oracleclient.oracleconnection(` 
    "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=myhost.host)(PORT=1800)) ` 
    (CONNECT_DATA=(SERVICE_NAME=myservicename)));User Id=myid;Password=mypassword;"); 

    $query = "SELECT country, asset FROM table " 
    $set = new-object system.data.dataset 
    $adapter = new-object system.data.oracleclient.oracledataadapter ($query, $connection) 
    $adapter.Fill($set) | Out-Null 
    $table = new-object system.data.datatable 
    $table = $set.Tables[0] 
    return ,$table 
    } 
}