> Tech > Si seulement j’avais un BLOB

Si seulement j’avais un BLOB

Tech - Par iTPro - Publié le 24 juin 2010
email

Utiliser le SqlDataReader pour extraire des données BLOB est comme extraire des données de type caractère et numérique, mais avec de grosses différences. La principale est que dans ADO.NET, il faut utiliser le flag CommandBehavior.SequentialAccess sur la méthode ExecuteReader de l'objet Command pour donner au SqlDataReader la possibilité d'extraire des

Si seulement j’avais un BLOB

données BLOB. Quand votre application appelle la méthode
ExecuteReader, qui instancie le SqlDataReader, le flag
CommandBehavior.SequentialAccess change le comportement
par défaut du SqlDataReader à  plusieurs égards.
Premièrement, CommandBehavior.SequentialAccess
permet à  l’application de sauter des colonnes sélectionnées
que le SqlDataReader renvoie. En principe, quand vous utilisez
le SqlDataReader, vous devez accéder aux colonnes dans
l’ordre où le SqlDataReader les renvoie. Mais quand vous
utilisez le flag CommandBehavior. SequentialAccess, votre application peut sauter par-dessus une
ou plusieurs des colonnes renvoyées
dans le flux de données. Il devient donc
possible de sauter une ou plusieurs colonnes
inintéressantes dans le jeu de résultats
et d’aller directement à  la colonne
BLOB qui vous intéresse. Sachez
toutefois qu’une fois que l’application a
lu au-delà  d’un certain point dans le flux
des données renvoyées, elle ne peut
plus rien lire avant cet emplacement.
Le flag CommandBehavior.SequentialAccess
change le comportement
par défaut de SqlDataReader
d’une deuxième manière : il désactive le
mode de buffering normal qui permet
au SqlDataReader de renvoyer une ligne
à  la fois. Au lieu de cela, le flag fait passer
les résultats de la base de données à 
l’application, en un flux continu. La
désactivation du buffering des données
permet au SqlDataReader d’extraire de
grands objets BLOB.
Voyons un exemple qui montre
comment utiliser le SqlDataReader pour
extraire des photos stockées dans une
colonne image SQL Server. La sous-routine
BLOBDataReader Export du listing
1
montre comment utiliser le SqlData
Reader pour extraire des données
BLOB et les écrire dans le système de fichiers.
La sous-routine commence par
créer un nouvel objet SqlConnection
nommé cn et un nouvel objet Sql
Command nommé cmd. Dans le listing
1
, l’objet SqlCommand contient une
instruction SELECT qui extrait de
BLOBTable la colonne blob_object dans
laquelle la valeur de la colonne blob_id
est 1. BLOBTable utilise le schéma suivant
dans lequel la colonne blob_object
est un type de donnée image :

CREATE TABLE BLOBTable
  (blob_id int IDENTITY(1,1),
  blob_filename varchar(256),
  blob_object image)

Ensuite, la sous-routine déclare un groupe de variables de
travail. Comme cette sous-routine exporte le contenu d’une
colonne BLOB dans le système de fichiers, elle a besoin d’un
mécanisme permettant d’écrire des fichiers binaires et c’est
précisément ce que font les objets fs FileStream et bw
BinaryWriter. Pour utiliser ces objets, vous devez importer
dans votre application à  la fois le namespace System.
Data.SqlClient qui supporte l’accès à  la base de données SQL
Server et le namespace .NET System.IO, en ajoutant les directives
d’importation suivantes à  votre projet :

Imports System.Data.SqlClient
Imports System.IO

Vous allez utiliser l’ensemble suivant de variables de la sous-routine du listing 1 pour transférer des données du
SqlDataReader dans le FileStream. La variable bufferSize définit
la quantité de données à  lire et outbyte est une matrice
d’octets qui joue le rôle de zone de garde temporaire. Comme
on le verra plus loin, vous utiliserez des variables retval et
startIndex avec le SqlDataReader pour extraire les données
BLOB.
Une fois que vous avez déclaré les variables de travail, la
section suivante dans la sous-routine crée l’objet FileStream
en passant trois paramètres au constructeur du FileStream (le
mécanisme qui crée une instance d’un objet). Le premier paramètre
spécifie le nom du fichier pour la sortie. Le deuxième
paramètre utilise l’énumérateur FileMode FileMode.Open
OrCreate pour préciser que si le fichier existe déjà , l’objet
FileStream l’ouvrira ; sinon, l’objet FileStream créera un nouveau
fichier. Le troisième paramètre utilise l’énumérateur
FileAccessWrite pour ouvrir le fichier à  des fins d’écriture,
permettant à  la sous-routine d’écrire des données binaires
dans le fichier de sortie. La sous-routine crée ensuite l’objet
BinaryWriter nommé bw et le rattache à  l’objet fs FileStream.
Ensuite, le code déclare un nouveau SqlDataReader nommé
rdr et utilise un block Try pour ouvrir la connexion et exécuter le SqlDataReader. Si une erreur se
produit à  l’intérieur du bloc Try, le code
exécute le bloc Catch à  la fin de la
sous-routine pour afficher une boîte de
message qui vous signale l’erreur.
Dans cet exemple, la partie la plus
importante du code se trouve au renvoi
A du listing 1, où j’utilise l’option
CommandBehavior.SequentialAccess
de ExecuteReader pour valider l’accès
par streaming aux données BLOB.
Ensuite, j’utilise une boucle While pour
lire les données que renvoie la requête
associée à  l’objet SQLCommand. Dans
ce cas, les données sont le contenu de
la colonne Picture. Par souci de simplicité,
cet exemple n’extrait qu’une colonne
d’image. Mais SQL Server n’impose
aucune restriction au mélange de
colonnes d’image avec des données de
type caractère et numérique dans le
même jeu de résultats. A l’intérieur de
la boucle While, le code lit une tranche
de données binaires à  partir de la colonne
Picture et écrit les données, une
tranche à  la fois, dans l’objet bw
BinaryWriter. La variable startIndex spécifie
la colonne dans le flux de données
qui marque l’endroit où la sous-routine
lira les données binaires.
La seconde partie la plus importante
du code se situe au renvoi B, où la
sous-routine utilise la méthode Get-
Bytes de rdr SqlDataReader pour lire les
données à  partir du SqlDataReader. Le
premier paramètre de la méthode
GetBytes spécifie la valeur d’index de la
colonne que le jeu de résultats renvoie.
La valeur de ce paramètre est mise à 
zéro parce que cet exemple ne renvoie
qu’une colonne. Le deuxième paramètre
spécifie la colonne dans le jeu de
résultats où la méthode GetBytes commencera
à  extraire des données. Le
troisième paramètre est une matrice
d’octets nommée bBLOBStorage qui
stockera les données binaires renvoyées
par la méthode GetBytes. Le
quatrième paramètre indique le point
dans le flux de données où le SqlData
Reader commencera à  lire les données.
Le cinquième paramètre de la méthode
GetBytes spécifie le nombre d’octets
que cette méthode extraira. Si le
nombre d’octets que vous indiquez
dans le cinquième paramètre dépasse la
taille de buffer disponible que vous avez
spécifiée dans le troisième paramètre, la
méthode GetBytes exprimera une exception.
Ensuite, au renvoi C, une boucle
While écrit les données binaires du rdr
SqlDataReader dans la matrice bBLOB
Storage jusqu’à  ce que la variable retval
soit égale à  la bufferSize, indiquant que
la méthode GetBytes a lu toutes les
données à  partir du SqlDataReader.
Ensuite, le code appelle la méthode
Write du BinaryWriter pour écrire la dernière
tranche de données binaires dans
le système de fichiers. Le code appelle
la méthode Flush pour effacer toutes
les données du buffer interne de bw
BinaryWriter et les écrire sur disque.
Cette opération de nettoyage est importante
parce qu’il faut renvoyer au
système la mémoire que votre application
utilise. Ensuite, le code ferme le bw
BinaryWriter et les objets fs FileStream
associés.
Une fois qu’ADO.NET a lu toutes les
données BLOB provenant du SqlData-
Reader et les a écrites dans le fichier de
sortie, la boucle While extérieure se termine
et le SqlDataReader utilise la méthode
Close pour terminer sa connexion
avec la base de données SQL
Server. Après quoi, la sous-routine
utilise la méthode FromFile de la classe
Image pour lire le tempExportBLOB
File à  partir du disque et attribue le
contenu du fichier à  la propriété image
d’un contrôle Picture Box. La figure 1
montre le résultat de la sous-routine
BLOBDataReaderExport.
Le code du listing 1 a d’abord exporté
le BLOB dans un fichier avant de
l’afficher dans un contrôle Picture Box.
Cependant, vous pourriez vouloir
mettre le contenu de l’image graphique
dans la boîte picture box sans utiliser un
fichier temporaire parce que la création de celui-ci demande du temps supplémentaire
et sollicite de l’I/O système additionnel.
Heureusement, vous pouvez
rendre votre application plus rapide et
plus efficace en utilisant le contournement
.NET WinForms que je décris dans
l’encadré « Utiliser le WinForm Data
Binding avec des BLOB ».

Téléchargez gratuitement cette ressource

Endpoint Security : Guide de Mise en œuvre

Endpoint Security : Guide de Mise en œuvre

Détournement d’applications légitimes, élévation de privilèges, logiciels malveillants furtifs : comment les solutions de Endpoint Security permettent elles de faire face aux nouvelles techniques d'attaques complexes ? Découvrez, dans ce Guide Endpoint Security, les perspectives associées à leur mise en œuvre.

Tech - Par iTPro - Publié le 24 juin 2010