Strange behavior in PowerShell function returning DataSet/DataTable

前端 未结 3 801
轮回少年
轮回少年 2020-12-01 14:38

This is driving me crazy. I have a library I source from multiple scripts, which contains the following function:

function lib_open_dataset([string] $sql) {
         


        
相关标签:
3条回答
  • 2020-12-01 14:58

    You can use the comma operator to wrap the rows collection in an array so that when the array is unrolled you wind up with the original rows collection e.g.:

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

    Essentially you can't prevent PowerShell from unrolling arrays/collections. The best you can do is workaround that behavior by wrapping the array/collection within another, single element array.

    0 讨论(0)
  • 2020-12-01 15:03

    PowerShell special-cases the DataTable internally. It does not implement any of the usual suspect interfaces like ICollection, IList or IEnumerable which normally trigger the unrolling. You can dig into this a bit with:

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

    Yet:

    PS> $e = [management.automation.languageprimitives]::GetEnumerator($dt)
    PS> $e.gettype()
    
    IsPublic IsSerial Name                                     BaseType
    -------- -------- ----                                     --------
    False    False    RBTreeEnumerator                         System.ValueType
    

    -Oisin

    0 讨论(0)
  • 2020-12-01 15:06

    Oh yes, I've been struggeling with this one too until I got this post..(tnxs Keith !)

    2 things you need to indeed focus on a) prepend your returned object with the comma indeed b) when you're filling your adaptor, make sure to either assign the outcome to a (disposalble) variable or do an Out-Null

    I didn't do the Out-Null and even with a prepended comma, I kept getting a collection back (item 0= number of rows from the query, item1= the datatable) Drove my a bit crazy until I picked the Out-null parameter out.

    Very weird IMHO, as I'm asking specifically to return the datatable but kept getting the collection back, even with the "," in front

    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
      }
    }
    
    0 讨论(0)
提交回复
热议问题