2015-05-05 2 views
1

Я работаю над скриптом для извлечения данных из BLOB в базе данных SQL. Процесс экстракции отлично работает. Я хочу добавить в сценарий какой-то индикатор прогресса. У меня есть общее количество записей из SQL-запроса, а счетчик инкремента, который увеличивается для каждого экспортируемого файла. Инкрементный счетчик работает, но общий счетчик записей, который я попытался присвоить глобальной переменной, похоже, не сохраняет его значение. Я объявляю это неправильно?Глобальная переменная теряет значение вне цикла

## Export of "larger" Sql Server Blob to file    
## with GetBytes-Stream.   
# Configuration data  
$StartTime = Get-Date 
$Server = "server"; 
$UserID = "user"; 
$Password = "password"; 
$Database = "db"; 
$Dest = "C:\Users\me\Desktop\Test\"; 
$bufferSize = 8192; 

# Counts total rows 
$CountSql = "SELECT Count(extension) as countall from 
       (
        SELECT p.[people_id], right(pi.[file_name],4) as extension 
        FROM dbo.pictures as pi 
        INNER JOIN dbo.people AS p ON p.person_picture = pi.pictures_id 
        where left([image_type], 5) = 'image' 
       ) as countall" 

# Selects Data 
$Sql = "SELECT p.[people_id], pi.[image_file], right(pi.[file_name],4), ROW_NUMBER() OVER (ORDER BY people_id) as count 
     FROM dbo.pictures as pi 
     INNER JOIN dbo.people AS p ON p.person_picture = pi.pictures_id 
     where left([image_type], 5) = 'image'";  

# Open ADO.NET Connection    
$con = New-Object Data.SqlClient.SqlConnection;    
$con.ConnectionString = "Data Source=$Server;" +    
         "Integrated Security=False;" + 
         "User ID=$UserID;" + 
         "Password=$Password;" +   
         "Initial Catalog=$Database";    
$con.Open();    

# New Command and Reader for total row count 
$CountCmd = New-Object Data.SqlClient.SqlCommand $CountSql, $con; 
$crd = $CountCmd.ExecuteReader(); 
While ($crd.Read()) 
{ 
    $crd.GetValue($global:1) 
} 
$crd.Close(); 

# New Command and Reader for rest of data  
$cmd = New-Object Data.SqlClient.SqlCommand $Sql, $con;    
$rd = $cmd.ExecuteReader();    

# Create a byte array for the stream.    
$out = [array]::CreateInstance('Byte', $bufferSize)    

# Looping through records 
While ($rd.Read())    
{    
    $total = $global:1 
    $counter = ($rd.GetValue(3)); 
    Write-Output ("Exporting $counter of $total`: {0}" -f $rd.GetGUID(0)); 

    # New BinaryWriter    
    $fs = New-Object System.IO.FileStream ($Dest + $rd.GetGUID(0) + $rd.GetString(2)), Create, Write;    
    $bw = New-Object System.IO.BinaryWriter $fs;    

    $start = 0;    
    # Read first byte stream    
    $received = $rd.GetBytes(1, $start, $out, 0, $bufferSize - 1);    
    While ($received -gt 0)    
    {    
     $bw.Write($out, 0, $received);    
     $bw.Flush();    
     $start += $received;    
     # Read next byte stream    
     $received = $rd.GetBytes(1, $start, $out, 0, $bufferSize - 1);    
    }    

    $bw.Close();    
    $fs.Close();    
}    

# Closing & Disposing all objects    
$fs.Dispose();    
$rd.Close();    
$cmd.Dispose();    
$con.Close();    
$EndTime = Get-Date 
$TotalTime = $EndTime - $StartTime  
Write-Host ("Finished in {0:g}" -f $TotalTime) 

ВЫВОД

PS C:\Users\me> C:\Scripts\ExportImagesFromNTST.ps1 
21380 
Exporting 1 of : 3089b464-e667-4bf4-80b3-0002d582d4fa 
Exporting 2 of : 04cf7738-ae19-4771-92b8-0003c5f27947 
Exporting 3 of : 94485b5d-fe71-438d-a097-000ad185c915 

и так далее. 21380 должно быть $ 1, которое также должно быть $ total.

+2

Нигде в вашем скрипте вы присваиваете что-то '$ global: 1' и' $ total', присваиваемое только этой переменной неизвестным значением. – PetSerAl

ответ

1

Я думаю, что PetSerAl ударил ноготь по голове здесь. Вы создаете объект SqlCommand ($CountCmd), и из него создайте SqlDataReader ($crd), а затем сообщите $crd, чтобы использовать метод GetValue(), который принимает целое число как параметр, чтобы он знал, в каком столбце возвращается значение, но вы ссылается на глобальную переменную с именем «1», которая никогда не определяется, поэтому вы эффективно передаете $null этому методу, поэтому он не получает никакого значения. Я искренне удивлен, что он не бросает на вас ошибки прямо сейчас. Вероятно, вы захотите просто передать целое число 1 в качестве аргумента для этого метода и присвоить его в цикле While. Я честно предполагаю здесь, но от того, что я вижу, я думаю, что это должно быть:

$crd = $CountCmd.ExecuteReader(); 
While ($crd.Read()) 
{ 
    $Total = $crd.GetValue(0) 
} 
$crd.Close(); 

Я уверен, что присвоит значение первого столбца (который для этой команды SQL должна быть просто 1 строкой с 1 столбцом, правильно? Всего общее количество?), в любом случае, назначьте значение первого столбца для текущей строки . Затем позже вы можете указать просто отлично, чтобы обновить ваш прогресс.

Вы, сэр, необходимо изучить командлет write-progress, если хотите отслеживать прогресс, он идеально подходит для вашего скрипта.

+0

Индекс будет 0 для первого столбца, а не 1. Но я использовал это, и он работал отлично! Я по-прежнему получаю свои сценарии под меня - спасибо за вашу помощь. – user3140622

+0

Ах, мой SQL-fu слаб, сожалею об этом. Рад, что вы его работали, и я обновлю ответ, чтобы показать правильный код. – TheMadTechnician

+0

И я принял ваш совет и использовал запись прогресса! Это здорово! http://i.imgur.com/T9V0IkA.png – user3140622

Смежные вопросы