2014-03-02 2 views
3

배경 정보 :Powershell 수신 작업에서 DataSet을 반환 할 수 있습니까?

나는 현재 실행하는 아주 아주 오랜 시간이 걸립니다 여러 데이터베이스에 여러 SQL 연결을 만드는 응용 프로그램이 있습니다.

Powershell (.NET)은 다음 진행을 위해 "SQL-GET"기능이 완료 될 때까지 대기합니다. 나는 각각의 "SQL-GET"기능을 각각의 백그라운드 작업에서 동시에 발사하여이 응용 프로그램의 속도를 극적으로 높일 수 있다는 인상을 받고 있습니다. 그런 다음 완료되면 각 작업에서 데이터를 검색합니다. DataSet 시스템 개체로 이상적입니다.

이슈 1는 :

배경 작업에서 데이터를 검색, 난 단지 다시 System.Array 개체를 얻을 관리 할 수 ​​있습니다. 내가 실제로 무엇을했는지는 입니다. System.DataSet 개체입니다. 이는 앱 내의 모든 로직이 DataSet 객체에 의존하기 때문에 필요합니다.

강령 : 여기

는 SQL 연결을 생성하고 결과에 새로 생성 된 데이터 세트 개체가 반환을 작성하는 코드의 v.simple 슬라이스입니다. 치료를해라. $ 결과은 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 매개 변수로 래핑 된 VERY SAME CODE가 있습니다. 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 짓을하지만, 게시물, 블로그와 나는 걸쳐 넘어 모든 기사는이 문제를 해결 작업과 모든 종과 경적 관리에 대한 극단적 인 깊이로 이동하는 것

. powershell의 기본 특성은 receive-job cmdlet을 통해 배열을 반환하는 것입니까?

반환 식에 대해 stack post을 읽었습니다. 내가 뭔가를하고 있다고 생각 했어. 시도 : 모든 여전히 배열을 반환

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

.

나는 수동으로 데이터 집합 개체를 다시 데이터 집합 개체로 변환하는 것을 보았습니다. - 매우 더러운 것처럼 보일지라도 - 저는이 게임 데이터 개체가 통과 할 수있는 방법이 있어야한다고 생각합니다. 백그라운드 작업과 현재 세션으로!:)

반복하려면

기본적으로, 내가 좋아하는 것 모두가 ret_results는 데이터 집합 ... 또는 DataTable을로 수신-작업 cmdlet의 검색 오브젝트 $을하는 것입니다. 어느 쪽이든 받아 들일 것입니다. 단지 배열이 아닙니다 :)

답변

2

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] 반환해야한다고 지정했습니다. 특정 테이블 반복을 지정하면 해당 테이블을 설명하는 개체 (아마도 DataTable 또는이 경우 DataRows ...)가 예상 한 것처럼 DataSet 대신 반환됩니다.

  • DataTables에 행이 있습니다. DataTable에 둘 이상의 행이있는 경우 위와 같이 PowerShell은 DataRow 컬렉션에서이를 반환합니다. 단일 행이 반환되는 경우가 아니라는 사실을 알면 놀랄 수 있습니다. DataRow 객체 컬렉션 대신 단일 DataRow 객체 만 반환합니다.

  • 출력이 실제로 예상되는 경우 출력을 항상 @($results.Tables[0])으로 지정하여 컬렉션에서 항상 반환하도록 할 수 있습니다. 그렇게하면 항상 컬렉션을 기대할 수 있으며 컬렉션을 반복하여 개별 개체를 관리함으로써 결과 콘텐츠를 적절하게 처리 할 수 ​​있습니다.

+1

@ Hhyper-anthony, 빠른 답장을 보내 주셔서 감사합니다! 첫째, 위의 코드 예제에서 DataSet 대신 DataTable을 안전하게 대체 할 수 있도록 DataSet 개체를 사용하여 DataTable 개체 컬렉션을 저장한다는 것을 알았습니다. 추가 검사를 통해 반환되는 데이터가 실제로 System.Data.DataRow 개체의 배열이라는 점에서 절대적으로 맞습니다. 이것은 쉽게 DataTable에 다시 구성 할 수 있습니다. – Mitch