【问题标题】:Why is my SQL executed via Start-Job not returning the answer I expect?为什么我通过 Start-Job 执行的 SQL 没有返回我期望的答案?
【发布时间】:2015-10-17 20:12:52
【问题描述】:

我有一个托管在 SQL Server 2008 上的数据库,我的常规用户帐户无法访问该数据库。为了查询它,我需要使用我的特殊“管理员”帐户(只是另一个 AD 帐户,但与我的普通用户帐户在不同的组中)。

我想出了一个想法,即通过 Start-Job 在 Powershell 中使用后台作业来对该数据库运行查询,因为您可以使用与登录用户不同的凭据启动作业,因此数据库上的集成安全性可以正常工作.自从我的问题出现以来,我今天下午在 Google 上搜索了很多,看到一些人出于同样的原因采用这种方法,但他们的结果似乎确实有效——而我的结果却不是出于某种原因。

我有以下 powershell 代码:

[scriptblock]$sql_block = {
    $Query = "select * from some_table"
    $CW_DBConnection = New-Object Data.SqlClient.SQLConnection
    $CW_DBConnection.ConnectionString = "Data Source=someserver;Initial Catalog=some_database;Integrated Security=SSPI;"
    $CW_DBConnection.Open()

    $Command = New-Object Data.SqlClient.SqlCommand($Query,$CW_DBConnection)
    $Adapter = New-Object Data.SqlClient.SqlDataAdapter
    $DataSet = New-Object Data.DataSet

    $Adapter.SelectCommand = $Command
    [void]$Adapter.Fill($DataSet)

    $CW_DBConnection.Close()

    return $DataSet
}

我通过以下方式执行:

$mySQLJob = Start-Job -ScriptBlock $sql_block -Credential $(Get-Credential -UserName AD\MyAdminAccount -Message "Enter Admin Password")
Wait-Job $mySQLJob
$results = Receive-Job $mySQLJob

这一切都很顺利。然而,当我来询问结果对象时,我看到了这个:

$results
RunspaceId              : 975030ec-d336-4583-9260-48439bb34292
RemotingFormat          : Xml
SchemaSerializationMode : IncludeSchema
CaseSensitive           : False
DefaultViewManager      : {System.Data.DataViewManagerListItemTypeDescriptor}
EnforceConstraints      : True
DataSetName             : NewDataSet
Namespace               :
Prefix                  :
ExtendedProperties      : {}
HasErrors               : False
IsInitialized           : True
Locale                  : en-GB
Site                    :
Relations               : {}
Tables                  : {System.Data.DataRow}
Container               :
DesignMode              : False
ContainsListCollection  : True

当我尝试进入表格位时:

$results.Tables[0]
System.Data.DataRow

$results.Tables[0].GetType()
IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     ArrayList                                System.Object

$results.Tables[0][0]
System.Data.DataRow

$results.Tables[0][0].GetType()
IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

从字面上看,结果就是字符串“System.Data.DataRow”。

我在哪里搞砸了?

注意 - 从实际上以我的管理员身份执行的 powershell 会话运行它,而不是通过 Start-Job 执行它(即仅执行 SQL 位内联)按预期工作,我从数据库中获取实际数据。

【问题讨论】:

    标签: sql sql-server-2008 powershell jobs powershell-4.0


    【解决方案1】:

    当我发布这个问题时,我已经在Can Powershell Receive-Job return a DataSet? 阅读了这个问题 - 但显然我没有仔细阅读它 - 因为工作答案返回的不是顶级 DataSet 对象,而是 Tables[0] 属性就可以了。

    我今天早上更改了我的脚本块以返回它,你瞧,我现在得到了实际的 SQL 数据。

    因此,Receive-Job 似乎没有将它返回的对象序列化到足够的深度,您可以返回任意对象(尽管我想您可以尝试自己序列化它们 - 我还没有尝试过。更新:见下面)。

    所以,总结起来就是一行的变化

    return $DataSet
    

    return $DataSet.Tables[0]
    

    成功了。

    更新:我现在尝试了“自己序列化”的方法,这似乎工作正常。所以首先你更新脚本块以在最后执行此操作:

    $Serialized_DataSet = [System.Management.Automation.PSSerializer]::Serialize($DataSet,2)
    return $Serialized_DataSet
    

    然后当您想要返回结果时:

    $results = Receive-Job $mySQLJob
    $deserialized_results = [System.Management.Automation.PSSerializer]::Deserialize($results)
    

    然后您可以看到 $deserialized_results.Tables[0] 实际上包含您可以使用的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-09
      • 1970-01-01
      • 2018-01-14
      • 2012-06-15
      • 1970-01-01
      • 2018-08-07
      • 1970-01-01
      相关资源
      最近更新 更多