如何从PowerShell函数返回特定数据类型,即DataTable

Emi*_*mil 4 powershell

我一直在尝试编写一个返回初始化[System.Data.DataTable]对象数据类型的实用程序函数.

我知道恼人的PowerShell函数返回行为,它试图将所有内容"展开"为[System.Array]返回类型.以前我一直设法解决这个问题.通常使用"逗号技巧"来返回你自己的阵列@(,$result)工作 - 但这次这似乎没有什么区别,我已经用完了选项......

我通常使用的另一个技巧是$nullProcess块中的赋值(请参阅下面的代码) - 这样我愚弄了管道,没有什么可以在输出上"展开"...

我不是不可能得到答案,到目前为止根据我的经验在PowerShell中没有什么是不可能的:)

这是我的代码:

function Get-SourceDataTable 
{
    [OutputType([System.Data.DataTable])]
    [cmdletbinding()]
    param(
        [parameter(Mandatory=$true, Position=0)]
        [System.Data.SqlClient.SqlBulkCopy] $Destination,
        [parameter(Mandatory=$true, Position=1)]
        [System.Collections.Specialized.OrderedDictionary] $ColumnDefinition,
        [parameter(Mandatory=$false, Position=2)]
        [int]$ColumnStartIndex = 0
    )
    BEGIN{
        $datatable = New-Object System.Data.DataTable
        $colIndex = $ColumnStartIndex 
    }
    PROCESS{
        $ColumnDefinition.Keys | 
        foreach {
            $null = $datatable.Columns.Add($_, $ColumnDefinition[$_])   # define each column name and data type
            $null = $Destination.ColumnMappings.Add($_, $colIndex) # map column to destination table
            $colIndex++
        }
    }
    END{
        return ,$datatable
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望有人可以让这段代码工作......

Bur*_*ris 7

而不是return使用Write-Output -NoEnumerate.例如:

function New-DataTable {
   $datatable = New-Object System.Data.DataTable
   $null = $datatable.Columns.Add("x",[int])
   $null = $datatable.Columns.Add("y",[int])
   $null = $datatable.Rows.Add(@(1,2))
   $null = $dataTable.Rows.Add(@(3,4))
   Write-Output -NoEnumerate $datatable
}

New-DataTable | Get-Member
Run Code Online (Sandbox Code Playgroud)

但请注意,如果您只是键入New-DataTable,它可能看起来像枚举行,但会Get-Member告诉您返回的实际类型.


Emi*_*mil 7

DataTable当我用来LoadWithPartialName加载包含类型的程序集并将其通过管道输出时,我从问题中得到了返回类型的函数Out-Null

不要问我为什么,如果你知道原因,请随时发表评论。

工作功能代码如下。请注意,return 语句不是必需的,我只是用它来提高代码可读性:

function Get-SourceDataTable 
{
    [OutputType([System.Data.DataTable])]
    [cmdletbinding()]
    param(
        [parameter(Mandatory=$true, Position=0)]
        [System.Data.SqlClient.SqlBulkCopy] $Destination,
        [parameter(Mandatory=$true, Position=1)]
        [System.Collections.Specialized.OrderedDictionary] $ColumnDefinition,
        [parameter(Mandatory=$false, Position=2)]
        [int]$ColumnStartIndex = 0
    )
    BEGIN{
        [System.Reflection.Assembly]::LoadWithPartialName("System.Data") | Out-Null
        $datatable = New-Object System.Data.DataTable
        $colIndex = $ColumnStartIndex 
    }
    PROCESS{
        $ColumnDefinition.Keys | 
        foreach {
            $null = $datatable.Columns.Add($_, $ColumnDefinition[$_])   # define each column name and data type
            $null = $Destination.ColumnMappings.Add($_, $colIndex) # map column to destination table
            $colIndex++
        }
    }
    END{
        return ,$datatable
    }
}
Run Code Online (Sandbox Code Playgroud)

总结强制 PowerShell 函数返回特定数据类型问题的所有已知可能解决方案:

  • 使用$null作业
  • 使用逗号返回数组,$variable
  • 使用LoadWithPartialName("Assembly.Name") | Out-Null
  • 用于Write-Output -NoEnumerate $variable返回类型 - 归功于Burt_Harris

最后,在Burt_Harris的输入之后(感谢 Burt!),这个问题的函数的最终工作版本是这样的:

function Get-SourceDataTable 
{
    [OutputType([System.Data.DataTable])]
    [cmdletbinding()]
    param(
        [parameter(Mandatory=$true, Position=0)]
        [System.Data.SqlClient.SqlBulkCopy] $Destination,
        [parameter(Mandatory=$true, Position=1)]
        [System.Collections.Specialized.OrderedDictionary] $ColumnDefinition,
        [parameter(Mandatory=$false, Position=2)]
        [int]$ColumnStartIndex = 0
    )
    BEGIN{
        #[System.Reflection.Assembly]::LoadWithPartialName("System.Data") | Out-Null
        $datatable = New-Object System.Data.DataTable
        $colIndex = $ColumnStartIndex 
    }
    PROCESS{
        $ColumnDefinition.Keys | 
        foreach {
            $null = $datatable.Columns.Add($_, $ColumnDefinition[$_])   # define each column name and data type
            $null = $Destination.ColumnMappings.Add($_, $colIndex) # map column to destination table
            $colIndex++
        }
    }
    END{
        #return ,$datatable
        Write-Output -NoEnumerate $datatable
    }
}
Run Code Online (Sandbox Code Playgroud)