4

背景情報:

現在、実行に非常に長い時間がかかる複数のデータベースに対して複数の SQL 接続を行うアプリケーションがあります。

Powershell (.NET) は、進行中の各 " SQL-GET " 関数が終了するのを待ってから、次の関数を起動できます。それぞれの「 SQL-GET」関数を独自のバックグラウンド ジョブで同時に起動することにより、このアプリを劇的に高速化できるという印象を受けました。その後、各ジョブが終了したら、各ジョブからデータを取得します。理想的には DataSet システム オブジェクトとして。

問題

バックグラウンド ジョブからデータを取得するとき、 System.Arrayオブジェクトを取得することしかできません。私が実際に求めているのは、System.DataSetオブジェクトです。これは、アプリ内のすべてのロジックが DataSet オブジェクトに依存しているため必要です。

コード:

これは、SQL 接続を作成し、新しく作成されたデータセット オブジェクトに返された結果を入力するコードの v.simple スライスです。御馳走を働きます。$resultsは DataSet オブジェクトであり、これをうまく操作できます。

$query = "SELECT * FROM [database]..[table] WHERE column = '123456'"

$Connection = New-Object System.Data.SqlClient.SQLConnection      
$ConnectionString = "Server='SERVER';Database='DATABASE';User ID='SQL_USER';Password='SQL_PASSWORD'"  
$Connection.ConnectionString = $ConnectionString     
$Connection.Open() 
$Command = New-Object system.Data.SqlClient.SqlCommand($Query,$Connection) 
$Adapter = New-Object system.Data.SqlClient.SqlDataAdapter
$Adapter.SelectCommand = $Command
$Connection.Close() 
[System.Data.SqlClient.SqlConnection]::ClearAllPools()

$results = New-Object system.Data.DataSet 

[void]$Adapter.fill($results)

$results.Tables[0]

そして、これは非常に同じコードが新しいバックグラウンド ジョブの scriptblock パラメータにラップされています。Receive-Job を呼び出したときにのみ、データセットではなく配列が返されます。

     $test_job = Start-Job -ScriptBlock {

$query = "SELECT * FROM [database]..[table] WHERE column = '123456'"

$Connection = New-Object System.Data.SqlClient.SQLConnection      
$ConnectionString = "Server='SERVER';Database='DATABASE';User ID='SQL_USER';Password='SQL_PASSWORD'"  
$Connection.ConnectionString = $ConnectionString     
$Connection.Open() 
$Command = New-Object system.Data.SqlClient.SqlCommand($Query,$Connection) 
$Adapter = New-Object system.Data.SqlClient.SqlDataAdapter
$Adapter.SelectCommand = $Command
$Connection.Close() 
[System.Data.SqlClient.SqlConnection]::ClearAllPools()

$results = New-Object system.Data.DataSet 

[void]$Adapter.fill($results) 
return $results.Tables[0]

}

Wait-Job $test_job
$ret_results = Receive-Job $test_job

どんな助けでも大歓迎です!!!

これまでの研究:

私は古いGoogleをやったことがありますが、私が遭遇したすべての投稿、ブログ、および記事は、仕事の管理とこれに関するすべての機能について非常に深く掘り下げているようです. receive-jobコマンドレットを介してのみ配列を返すのは、powershellの根本的な性質ですか?

return 式に関するスタックの投稿を読みました。私は何かに乗っていると思った。試みた:

  • return $results.Tables[0]
  • return ,$results.Tables[0]
  • return ,$results

すべてが配列を返します。

私はかなり面倒なことに、手動で配列をデータセット オブジェクトに変換し直す人々を見てきました。私の現在のセッションに!:)

繰り返します:

基本的には、$ret_results オブジェクトを Receive-Job コマンドレットから取得して、DataSet にすること、または DataTable にすることだけが必要です。私はどちらかを取ります...配列ではありません:)

4

2 に答える 2

4

PowerShell では、任意の型の複数のオブジェクトのセットがコレクションで返されるのが一般的です。独自のテーブルを作成するこの変更された例を検討してください。

PS C:\> $job = Start-Job -ScriptBlock {
>>
>> $table = New-Object system.Data.DataTable “MyTable”
>>
>> $col1 = New-Object system.Data.DataColumn MyFirstCol,([string])
>> $col2 = New-Object system.Data.DataColumn MyIntCol,([int])
>>
>> $table.columns.add($col1)
>> $table.columns.add($col2)
>>
>> $row1 = $table.NewRow()
>> $row1.MyFirstCol = "FirstRow"
>> $row1.MyIntCol = 1
>> $row2 = $table.NewRow()
>> $row2.MyFirstCol = "SecondRow"
>> $row2.MyIntCol = 2
>>
>> $table.Rows.Add($row1)
>> $table.Rows.Add($row2)
>>
>> $dataSet = New-Object system.Data.DataSet
>> $dataSet.Tables.Add($table)
>>
>> $dataSet.Tables[0]
>>
>> }
>>
PS C:\> $output = Receive-Job -Job $job

出力を受け取りました。それで、私たちは何を手に入れましたか?

PS C:\> $output.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

あなたが説明したように、配列。しかし、それはオブジェクト全体です。にパイプすることによって、そのメンバーを個別に分析するとどうなるGet-Memberでしょうか?

PS C:\> $output | gm

   TypeName: Deserialized.System.Data.DataRow

Name               MemberType   Definition
----               ----------   ----------
ToString           Method       string ToString(), string ToString(string format, System.IFormatProvider formatProvi...
PSComputerName     NoteProperty System.String PSComputerName=localhost
PSShowComputerName NoteProperty System.Boolean PSShowComputerName=False
RunspaceId         NoteProperty System.Guid RunspaceId=186c51c3-d3a5-404c-9a4a-8ff3d3a7f024
MyFirstCol         Property     System.String {get;set;}
MyIntCol           Property     System.Int32 {get;set;}

PS C:\> $output


RunspaceId : 186c51c3-d3a5-404c-9a4a-8ff3d3a7f024
MyFirstCol : FirstRow
MyIntCol   : 1

RunspaceId : 186c51c3-d3a5-404c-9a4a-8ff3d3a7f024
MyFirstCol : SecondRow
MyIntCol   : 2

次の点を考慮してください。

  • あなたの仕事では、 を$results.Tables[0]返す必要があることを指定しました。特定の Tables 反復を指定することにより、そのテーブルを記述するオブジェクトを返します...おそらく DataTable、またはこの場合は DataRows... 期待しているように見える DataSet の代わりに?

  • DataTable には行があります。DataTable に複数の行がある場合、上記で説明したように、powershell はそれを DataRows のコレクションで返します。単一の行が返される場合はそうではないことを知って驚くかもしれません。DataRow オブジェクトのコレクションではなく、単一の DataRow オブジェクトのみが返されます。

  • これが実際に期待する出力である場合は、出力を として指定して、常にコレクションに返すように強制することができます@($results.Tables[0])。こうすることで、常にコレクションを予期し、結果のコンテンツを適切に処理できます (コレクションを反復処理して個々のオブジェクトを管理することにより)。

于 2014-03-02T04:39:14.163 に答える