From Blob to File via OleDb

Dziś znów postaram się zaprezentować problem z życia wzięty. Mianowicie musiałem stanąć przed problemem wyciągnięcia plików zapisanych w bazie danych w formie klasycznego BLOB’a. Sposobów na wykonanie tego zadania jest kilka, jednakże postaram się zaprezentować jedno z tych prostszych.

Najpierw spróbujmy podłączyć się do bazy danych w celu pobrania naszych zasobów. Do tego tworzymy odpowiedni connection string do naszej bazy danych oraz zapisujemy zapytanie SQL.

$DBServer = "DBSERVER"
$DataBase = "TESTOWA"
$ConnectionString = "Provider=sqloledb; Data Source=$DBServer; Initial Catalog=$DataBase; Integrated Security=SSPI;"
$SQLCommand = "SELECT <nazwa pliku>, <zawartość pliku>
FROM <tabela>"

Gdy mamy już przygotowane niezbędne informacje możemy przystąpić do sedna sprawy. Tworzymy obiekt OleDbConnection odpowiadający jak sama nazwa wskazuje za połączenie do bazy danych oraz OleDbCommand, który będzie zawierał nasze zapytanie w formie obiektu OleDB.

$OleDbConnection = New-Object System.Data.OleDb.OleDbConnection $ConnectionString
$OleDbCommand = New-Object System.Data.OleDb.OleDbCommand $SQLCommand,$OleDbConnection

Posiadając już odpowiednie “interfejsy” możemy przystąpić do pobierania danych z bazy. Do tego celu otwieramy połączenie do bazy danych.

$OleDbConnection.Open()

Tworzymy obiekt OleDbDataAdapter, który wyśle zapytanie z obiektu OleDbCommand do bazy danych. Ostatecznie obiekt ten poprzez wywołanie odpowiedniej metody zwróci wynik zapytania do kolejnego obiektu czyli DataSet.

$OleDbDataAdapter = New-Object System.Data.OleDb.OleDbDataAdapter $OleDbCommand
$DataSet = New-Object System.Data.DataSet
[void] $OleDbDataAdapter.Fill($DataSet)
$DataRows = $DataSet.Tables | Select-Object -Expand Rows

Cały proces w zależności od ilości pobieranych danych może troszkę potrwać.

Ostatecznie zamykamy połączenie do bazy, gdyż niezbędne informacje posiadamy już zapisane w naszej zmiennej.

$OleDbConnection.Close()

Drugim etapem operacji jest zapisanie danych ze zmiennej do pliku/ów. Do tego celu całą operację będziemy wykonywali w pętli foreach, która będzie przetwarzała każdy wiersz zwrócony z bazy danych osobno.

Foreach($DataRow in $DataRows)
{…} 

Tworzymy obiekt FileStream, który będzie reprezentował nasz plik.

$FileStream = New-Object System.IO.FileStream ($DataRow.FileName), Create, Write

Dodatkowo tworzymy obiekt BinaryWriter, który będzie powiedzmy interfejsem dla binarnych danych ze zmiennej, a naszym plikiem.

$BinaryWriter = New-Object System.IO.BinaryWriter $FileStream

Cały zapis odbywa się poprzez wykorzystanie metody Write obiektu BinaryWriter.

$BinaryWriter.Write($DataRow.FileContent)

Na zakończenie pozostaje jedynie wyczyścić bufor obiektu BinaryWriter. Dodatkowo musimy również zakończyć pracę obiektów BinaryWriter oraz FileStream.

$BinaryWriter.Flush()
$BinaryWriter.Close()
$FileStream.Close()

Całość wygląda następująco:

$DBServer = "DBSERVER"
$DataBase = "TESTOWA"
$ConnectionString = "Provider=sqloledb; Data Source=$DBServer; Initial Catalog=$DataBase; Integrated Security=SSPI;"
$SQLCommand =  "SELECT <nazwa pliku>, <zawartość pliku> FROM <tabela>"

$OleDbConnection = New-Object System.Data.OleDb.OleDbConnection $ConnectionString
$OleDbCommand = New-Object System.Data.OleDb.OleDbCommand $SQLCommand,$OleDbConnection

$OleDbConnection.Open()

$OleDbDataAdapter = New-Object System.Data.OleDb.OleDbDataAdapter $OleDbCommand
$DataSet = New-Object System.Data.DataSet
[void] $OleDbDataAdapter.Fill($DataSet)

$OleDbConnection.Close()

$DataRows = $DataSet.Tables | Select-Object -Expand Rows
Foreach($DataRow in $DataRows)
{
	$FileStream = New-Object System.IO.FileStream ($DataRow.FileName), Create, Write
	$BinaryWriter = New-Object System.IO.BinaryWriter $FileStream

	$BinaryWriter.Write($DataRow.FileContent)
	$BinaryWriter.Flush()
	$BinaryWriter.Close()
	$FileStream.Close()
}

Plusem tego rozwiązania jest łatwość wykorzystania, gdyż w momencie gdy ktoś programował praktycznie w dowolnym języku obiektowym sama idea działania będzie zbliżona. Niemniej jednak minusem może się tutaj okazać brak buforowania danych. Gdyż najpierw pobieramy cały strumień danych z bazy, a dopiero później zaczynamy zapisywać je w postaci plików. Jednakże, w przypadku pobierania nie wielkiej partii małych plików, np. zdjęć może się to okazać wystarczającym rozwiązaniem.

Reklamy

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s