使用PSTypeNames来改变Invoke-SqlCmd的数据元素

时间:2016-05-11 17:08:02

标签: sql-server powershell powershell-v5.0 invoke-sqlcmd

我想开发一种模式,可以轻松切换视图'执行连接到数据库的PowerShell函数时的数据。

根据这篇文章Quick Hits: Set the Default Property Display in PowerShell on Custom Objects,我创建了:

<#
.NOTES
Assumes a table named `Person` with columns `FirstName`,`LastName`,`Gender`,`BirthDate`,`City`,`Region`,`Telephone`
#>
function Get-CustomObject {

    param(
        [Parameter(Position=0)]
        [ValidateSet('Demographics','Contact','All')]
        [alias('v')]
        [System.String]$View='All'
    )

    Remove-TypeData -TypeName User.Information -ErrorAction SilentlyContinue

    Switch ($View) {
        'Demographics' { Update-TypeData -TypeName User.Information -DefaultDisplayPropertySet FirstName,LastName,Gender }
        'Contact' { Update-TypeData -TypeName User.Information -DefaultDisplayPropertySet City,Region,Telephone }
    }

    Invoke-SqlCmd -ServerInstance ServerName -Database DatabaseName -Query 'SELECT * FROM Person' | 

        ForEach {

            # assign typename
            $_.PSTypeNames.Insert(0,'User.Information')

            # return object
            $_

    } # / ForEach

}

如果未指定-View参数,则使用All设置:

PS> Get-CustomObject

Id         : 20
FirstName  : DCD65A17
LastName   : 05016468
City       : 4DF12729
Region     : MN
Telephone  : 6125551212
Gender     : F
Occupation : abcdefghij
Birthdate  : 1/1/1900 12:00:00 AM

指定-View参数时,将修改默认视图:

PS> Get-CustomObject Contact

City     Region Telephone
----     ------ ---------
A78D794C MN     6125551212
FDB79B27 MN     6125551212
49D073FE MN     6125551212
0716DF7E MN     6125551212
29FF9D4E MN     6125551212

问题:

  • 有更好的方法吗?
  • 可以为整个查询设置PSTypeNames,而不必将其分配给每一行(因此无需Foreach)吗?
  • 是否可以为验证集中的每个项目分配别名?例如,PS> Get-CustomObject d将使用Demographics视图。

1 个答案:

答案 0 :(得分:2)

有更好的方法吗?

据我所知。如果Invoke-SQLCMD的输出是pscustomobject或其他“通用”类型,例如DataRow等,那么您需要修改类型名称,因为视图链接到类型名称。

是否可以为整个查询设置PSTypeNames,而不必将其分配给每一行(从而无需Foreach)? < / p>

如果cmdlet不支持,则不行。

powershell中的视图是根据第一个返回的对象选择的,因为管道的工作原理(不知道有多少对象会出现),所以如果你能负担得起在输出中包含一个虚拟对象,你可以从在管道中抛出一个带有正确typename的虚拟对象,以获得正确的视图。这样你就不需要修改其他对象了。

请注意,其他对象的类型名称仍然是pscustomobjectDataRow等,所以这只是让视图生效的黑客。

例如:

<#
.NOTES
Assumes a table named `Person` with columns `FirstName`,`LastName`,`Gender`,`BirthDate`,`City`,`Region`,`Telephone`
#>
function Get-CustomObject {

    param(
        [Parameter(Position=0)]
        [ValidateSet('Demographics','Contact','All')]
        [alias('v')]
        [System.String]$View='All'
    )

    Remove-TypeData -TypeName User.Information -ErrorAction SilentlyContinue

    Switch ($View) {
        'Demographics' { Update-TypeData -TypeName User.Information -DefaultDisplayPropertySet FirstName,LastName,Gender }
        'Contact' { Update-TypeData -TypeName User.Information -DefaultDisplayPropertySet City,Region,Telephone }
    }

    #Output dummy-object (you can remove every property except pstypename and ONE random property,
    #but to avoid "null value expcetion" later I would include the properties you know about
    New-Object psobject @{
        pstypename = "User.Information"
        FirstName = "N/A"
        LastName = "N/A"
        Gender = "N/A"
        BirthDate = "N/A"
        City = "N/A"
        Region = "N/A"
        Telephone = "N/A"
    }

    #Real data
    Invoke-SqlCmd -ServerInstance ServerName -Database DatabaseName -Query 'SELECT * FROM Person'

}

是否可以为验证集中的每个项目分配别名?例如,PS> Get-CustomObject d会使用Demographics视图。

不使用ValidateSet AFAIK,因为它验证了确切的值。如果您有PowerShell 5,则可以使用enum替换它。

样品:

enum GetCustomObjectViews {
    Demographics
    Contact
    All
}

function Get-CustomObject {

    param(
        [Parameter(Position=0)]
        [alias('v')]
        [GetCustomObjectViews]$View='All'
    )

    #....    
}

Get-CustomObject -View d