1

我想开发一种模式,以便在执行连接到数据库的 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视图。
4

1 回答 1

2

有没有更有效的方法来做到这一点?

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

是否可以PSTypeNames为整个查询设置 ,而不必将其分配给每一行(从而消除对 的需要Foreach)?

如果 cmdlet 不支持它,则不会。

powershell 中的视图是基于第一个返回的对象选择的,因为管道是如何工作的(不知道有多少对象即将到来),所以如果你能负担得起在输出中包含一个虚拟对象,你可以从抛出一个虚拟对象开始-object 在管道中使用正确的类型名以获得正确的视图。这样您就不需要修改其他对象。

请注意,其他对象的类型名仍然是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视图。

不适用于ValidateSetAFAIK,因为它验证了确切的值。如果您有 PowerShell 5,则可以将其替换为可以使用的enum

样本:

enum GetCustomObjectViews {
    Demographics
    Contact
    All
}

function Get-CustomObject {

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

    #....    
}

Get-CustomObject -View d
于 2016-05-11T17:43:47.640 回答