Background Info:
I have an application that makes several SQL connections to multiple databases which currently takes a very very long time to execute.
Powershell (.NET) will wait for each proceeding "SQL-GET" function to finish before it can fire off the next. I am under the impression I can speed this app up dramatically by firing each "SQL-GET" function in their own background job simultaneously!I will then retrieve the data from each job as they finish. Ideally as a DataSet system object.
The Issues:
When retrieving the data from the background job, I can ONLY manage to get a System.Array object back. What I am actually after, is a System.DataSet object. This is necessary because all the logic within the app is dependant on a DataSet object.
The Code:
Here is a v.simple slice of code that will create a sql connection and fill a newly created dataset object with the results returned. Works a treat. The $results is a DataSet object and I can manipulate this nicely.
$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]
And here is that VERY SAME CODE wrapped into the scriptblock parameter of a new background job. Only upon calling Receive-Job, I get an array back, not a dataset.
$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
Any help would be greatly appreciated!!!
Research Thus Far:
I have done the old Google, but all of the posts, blogs and articles I stumble across seem to go into EXTREME depth about managing jobs and all the bells and whistles around this. Is it the underlying nature of powershell to ONLY return an array through the receive-job cmdlet?
I have read a stack post about the return expression. Thought I was on to something. Attempted:
return $results.Tables[0]
return ,$results.Tables[0]
return ,$results
All still return an array.
I have seen people, rather cumbersomely, manually transform the array back into a dataset object - though this seems very 'dirty' - I am pedantic and live in hope there must be a way for this magical dataset object to traverse through the background job and into my current session! :)
To reiterate:
Basically, all I would like is to have the $ret_results object retrieved from the Receive-Job cmdlet to be a DataSet...or even a DataTable. I'll take either...JUST NOT AN ARRAY :)