Home Page Home Page Articoli Gestire e sfruttare i campi BLOB usando .NET

Gestire e sfruttare i campi BLOB usando .NET

I database server sono software con una potenza elevata e offrono una vasta gamma di features che spesso non vengono utilizzate. Una di queste sono i campi BLOB (campi per contenere dati in formato binario). Vediamo in questo articolo come utilizzarli con .NET.
Autore: David De Giacomi Livello:
Database come archivio di file binari
Quasi ognuno di voi avrà sicuramente utilizzato un Database nel corso della sua vita da Programmatore. Generalmente però tutti lo utilizziamo per creare delle tabelle con tanti campi in cui andremo inserire Records con tutte le informazioni di cui abbiamo bisogno. Records che possono essere transazioni bancarie, utenti registrati presso un sito, o elenchi in genere.
I Database sono strumenti molto potenti e flessibili che ci permettono di fare tante cose.
Una di queste è la possibilità di inserire direttamente dati in formato binario quindi file eseguibili per esempio, file MP3, file video, PDF, immagini e via di seguito.
Il nostro database quindi può diventare con poca fatica un archivio di file.
Alcune case grosse come Oracle hanno prodotto addirittura delle estensioni al Database che vi permettono di trasformare il Database Server in un file System e sfruttarne la sua potenza per immagazzinare i file ed effettuare ricerche per esempio. E' un po' l'obbiettivo che ha anche Microsoft cioè di costruire un File System che si appoggia ad un Database (n.d.r. SQL Server) anche se in questo caso è un po' diverso rispetto a quello che fa Oracle con il suo prodotto Oracle Files.

Definizione di BLOBs
Abbiamo fatto una piccola introduzione ma non abbiamo ancora definito questa nuova entità cioè i BLOB nome che sta per Binary Large Objects letteralmente oggetti binari larghi o grossi come dimensione, dopo capiremo il significato di "large".
Un campo BLOB in un database serve quindi per immagazzinare dati Binari generici o specifici come indicato sopra (MP3, PDF, ecc.)
Quasi tutti i Database supportano i BLOBs, da Oracle a SQL Server fino a Microsoft Access e pure MySQL.

Pro e Contro dell'utilizzo di campi tipo BLOB
Non tutto è oro ciò che luccica. Certamente poter utilizzare i BLOB è una cosa eccezionale e utile. Pensate per esempio ad un negozio online che può immagazzinare in formato PDF tutte le fatture in formato elettronico emesse ai clienti.
Oppure un sito Web per avere una migliore gestione dei contenuti può immagazzinare tutte le immagini catalogandole per dimensione, tipo e occupazione di spazio.

Dicevamo prima del termine "large". Bene, tanto per fare un esempio e per capire che cosa effettivamente significhi posso dire che una colonna di tipo "image" su un Database SQL Server può contenere fino a circa 2 Giga di dati :-O. Parecchi vero ?
Si può capire con un minimo sforzo che problemi potreste avere a gestire tabelle di questo tipo con dati molto ingombranti. Le dimensioni dei vostri Database possono aumentare sensibilmente e gestire poi una mole di dati di questo tipo può diventare dispendioso in termini di tempo e appesantire il database server stesso. Anche dover fare un backup la cosa diventa complicata. Certo... se avete a disposizione ingenti quantità di denaro per acquistare hardware allora il problema non è così rilevante.
Vi consiglio quindi di pensare intensamente e ragionare prima di andare ad implementare soluzioni di questo tipo (che facciano uso di BLOB) prima che un giorno o l'altro i DB vadano fuori controllo e magari sia necessario ritornare su soluzioni più standard e più facili da gestire.


Gestire BLOBs con .NET
Nel nostro esempio utilizzeremo le classi SqlClient di .NET e quindi il Database SQL Server. Se dovete lavorare con Access invece dovrete utilizzare OleDb.
Mostreremo negli esempi seguenti come immagazzinare all'interno di un campo BLOB un'immagine a caso presa dal file system e poi effettuare il processo contrario, cioè estrarla dal Database e ripristinarla su disco in modo da renderla utilizzabile per ulteriori elaborazioni o spedirla ai vostri amici.

Come prima operazione creiamo una tabella su SQL Server con una colonna di tipo image che potrà ospitare i nostri dati, una colonna ID di tipo int che conterrà l'indice dell'immagine e una colonna ImageName di tipo nvarchar 50 che conterrà il nome del file.
E' possibile fare l'operazione utilizzando l'Enterprise Manager di SQL oppure anche con il Query Analyzer per chi conosce bene la sintassi SQL.



Per chi preferisce questo è lo script SQL per creare la tabella:


CREATE TABLE [dbo].[Images] (
[ID] [int] IDENTITY (1, 1) NOT NULL ,
[ImageData] [image] NULL ,
[ImageName] [nvarchar] (50) COLLATE Latin1_General_CI_AS NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO


Passiamo ora alla costruzione di una WinForm e a scrivere il codice necessario per inserire/estrarre l'immagine/i.
La Form creata è la seguente:



E' abbastanza semplice ed è composta da:

- Una TextBox chiamata txtFilepath che contiene il Path al file da leggere/scrivere
- Un Button chiamato cmdWriteBlob che contiene il codice per immagazzinare l'immagine nel DB
- Un Button chiamato cmdReadBlob che contiene il codice per estrapolare l'immagine dal DB
- Una Picture Box chiamata PictureBox1 per rappresentare l'immagine

Cominciamo a sottolineare che per far funzionare questo progetto è necessario referenziare i seguenti due namespaces:


using System.IO; //per l'accesso ai file su disco
using System.Data.SqlClient; //per l'accesso al Database SQL Server


Scrittura del BLOB nel Database
Come vedete la tabella che abbiamo creato è ancora vuota:



Fate un doppioclick sul button cmdWriteBlob e andiamo a digitare il seguente codice che ora spieghiamo in dettaglio:


//Apertura Connessione al Database
SqlConnection sqlconn=new SqlConnection("Server=Localhost;Initial Catalog=DBImmagini;UID=sa;PWD=sa");
sqlconn.Open();

//Legge i dati del file indicato nella casella di testo in memoria in un buffer
FileStream fs=new FileStream(txtFilepath.Text,FileMode.Open,FileAccess.Read);
byte[] dati = new byte[fs.Length];
fs.Read(dati,0,(int)fs.Length);
fs.Close();

//Crea un Command per l'inserimento nella Tabella
SqlCommand cmd=new SqlCommand("INSERT INTO Images (ImageData,ImageName) VALUES (@ImageData,@ImageName)",sqlconn);

//Aggiunge dei parametri al Command specificando i valori da inserire
SqlParameter par=cmd.Parameters.Add("@ImageData",SqlDbType.Image);
par.Value=dati;
par=cmd.Parameters.Add("@ImageName",SqlDbType.NVarChar,50);
par.Value=Path.GetFileName(txtFilepath.Text);

//Esegue l'inserimento
cmd.ExecuteNonQuery();

//Chiude la connessione
sqlconn.Close();


Come vedete i passi fondamentali sono quattro:

1) Apertura connessione al DB
2) Lettura del file da disco e riempimento del Buffer
3) Creazione di un SqlCommand e di SqlParameter specificando i dati
4) Eseguire il SqlCommand e chiudere la connessione al DB

Le parti forse meno comprensibili sono la 2) e la 3).
Utilizziamo la classe FileStream per aprire e leggere il file specificato nella textbox. Nel mio caso era c:\shot.png che è un file che dovete creare appositamente o se ne avete un altro anche di diverso tipo è uguale.

Viene poi creato un buffer, cioè un'area temporanea di memoria ove immagazzinare il file dopo la lettura:

byte[] dati = new byte[fs.Length];

Come vedete viene passato come parametro fs.Length che non è altro che la dimensione del file. Allochiamo quindi una sequenza di cellette (bytes) quanti sono i bytes del file in modo da contenerlo completamente.

In seguito, tramite la Read leggiamo il contenuto e lo immettiamo nel buffer appena creato:

fs.Read(dati,0,(int)fs.Length);

A questo punto è possibile creare un SqlCommand che avrà la Query di inserimento. Come vedete ci sono due parametri che cominciano con @. Successivamente infatti creiamo i due parametri e assegnamo loro il dato nel primo caso il nostro buffer di dati, nel secondo il nome del file (shot.png).

SqlParameter par=cmd.Parameters.Add("@ImageData",SqlDbType.Image);
par.Value=dati;


Ora potete lanciare il programma e premere il pulsante, questo è il risultato:



In questo momento il nostro file è immagazzinato nella tabella. I dati effettivi binari del file sono nel nostro campo BLOB che è contrassegnato dalla parola "Binary" che sta a significare, che lì ci sono dati binari. L'ID si incrementa automaticamente ed infatti parte da 1.


Lettura del BLOB dal Database e scrittura su disco
Il processo per leggere il file dal Database e scriverlo su disco è praticamente l'opposto. In questo caso faremo uso di un DataSet e di un DataAdapter che servirà per riempirlo.


//Apertura Connessione al Database
SqlConnection sqlconn=new SqlConnection("Server=Localhost;Initial Catalog=DBImages;UID=sa;PWD=sa");
sqlconn.Open();

//Creazione di DataAdapter e riempimento del DataSet
SqlDataAdapter da=new SqlDataAdapter("SELECT * FROM IMAGES",sqlconn);
DataSet ds=new DataSet();
da.Fill(ds);

//Allocazione di un Buffer per contenere i dati binari provenienti dal Database
byte[] dati = new byte[0];
dati=(byte[])ds.Tables[0].Rows[0]["ImageData"];

//Scrittura dei dati su disco
FileStream fs=new FileStream("C:\\" + ds.Tables[0].Rows[0]["ImageName"].ToString(),FileMode.Create,FileAccess.Write);
fs.Write(dati,0,dati.Length);
fs.Close();

//Chiusura connessione
sqlconn.Close();


A differenza della prima routine questa è anche più semplice.
Dopo aver aperto la connessione, utilizziamo un DataAdapter per recuperare tutti i dati dalla nostra tabella (SELECT * FROM Images). Facciamo un Fill su un DataSet appena creato ed otteniamo i nostri dati. (La connessione adesso si potrebbe anche chiudere, vista la natura di Database "disconnesso" del DataSet).

Viene creato anche in questo caso un Array di Byte vuoto (dimensione 0) a cui assegnamo in seguito il campo ImageData del Record con indice 0 del nostro DataSet cioè i dati della nostra Immagine.

Creiamo un oggetto FileStream per la scrittura su disco, avente per nome il contenuto della seconda colonna del nostro Database (ImageName) ossia il nome originale del file, e infine con il metodo Write scriviamo su disco i dati. Non ci resta che chiudere il FileStream e la connessione a DB.

Lanciate il programma premete ReadBlob e come per magia vi ritroverete sul disco il file ricostruito shot.png.


Visualizzare sulla WinForm il BLOB appena letto
La ciliegina sulla torta. Per chi non volesse scrivere su disco i file ma volesse semplicemente visualizzarli si può fare un'integrazione del codice ed usare un MemoryStream cioè una classe apposita che consente di memorizzare i dati letti in memoria invece che su disco.
Ecco il codice necessario:



//Crea un MemoryStream partendo dal nostro Buffer dati
MemoryStream ms=new MemoryStream(dati,0,dati.Length);

//Crea un'immagine usando come sorgente il MemoryStream
Image i=Image.FromStream(ms);

//Rappresenta l'immagine sulla PictureBox
pictureBox1.Image=i;


Ed ecco il risultato:



In allegato all'articolo c'è il progetto in linguaggio C#. Chi stesse usando Visual Basic .NET non troverà troppe difficoltà nel fare la conversione.


Conclusioni
Come al solito dei brevi e concisi esempi che vi permettono di capire le potenzialità offerte in questo caso da SQL Server (ma anche altri database le offrono) e dalle classi del .NET Framework che sono utili in quasi ogni scenario.
Conoscendo i BLOBs ora potete espandere e integrare le vostre applicazioni creando archivi e/o cataloghi di dati in modo da gestire più semplicemente e rapidamente le vostre informazioni testuali (Records classici di solo testo) e anche multimediali (mp3, immagini, altro). Un occhio di riguardo alle dimensioni dei file inseriti e alle prestazioni globali del Database. Buon divertimento!

Voto medio articolo: 4.9 Numero Voti: 19

File allegati


122_blob.zip (8 Kbyte)
David De Giacomi

David De Giacomi

MVP Program Logo Approda al mondo dell'informatica nell' Aprile del 1994. Un amico gli fa conoscere il Quick Basic del DOS. E' cosi che inizia la sua attività di sviluppatore. Prosegue il suo percorso con altri linguaggi (Visual Basic, Pascal, Java, ANSI C), fino ad arrivare a .NET. Per un certo periodo affianca all'attività ... Profilo completo

Articoli collegati

Importare dati di Excel con .NET tramite ODBC o OLEDB e Drag & Drop
Spesso in ambito aziendale è necessario adattare le proprie applicazioni e consentire che possano leggere e operare su file e dati provenienti dai tools della suite di Office fra cui uno dei più usati è Excel. Vediamo quindi come importare dati da file XLS tramite ODBC/OLEDB e Drag & Drop.
Autore: Marco Farina | Difficoltà:
Gestire le Access Control List (ACL) NTFS di file e directory con .NET
Scopriamo come nel .NET Framework 2.0 sia diventato facile recuperare e modificare la lista controllo accessi dei file e directory e in generale come gestire le ACL.
Autore: Marco Caruso | Difficoltà: | Commenti: 1 | Voto:
Costruire un client FTP usando il .NET Framework 2.0
In questo articolo tratteremo una delle novità più attese del .NET Framework 2.0, le classi per l'utilizzo del protocollo FTP. Realizzeremo un mini client FTP con alcune fra le funzionalità più comuni.
Autore: Giovanni Ferron | Difficoltà: | Commenti: 28
Alla scoperta di WMI, questo sconosciuto
WMI o Windows Management Instrumentation è un componente fondamentale del sistema operativo Windows. La sua utilità è permettere l'accesso a informazioni fondamentali del sistema, come informazioni sull'hardware, software, servizi, ecc. Vediamo come sfruttarlo con .NET.
Autore: Giovanni Ferron | Difficoltà: | Commenti: 2
Catturare immagini da una Webcam con .NET
In questo articolo mostreremo come è possibile costruire una applicazione per catturare immagini da una Webcam, utilizzando componenti già presenti in Windows, in questo caso l' Avicap32.dll
Autore: Giovanni Ferron | Difficoltà: | Commenti: 22 | Voto:
Usare il protocollo POP3 per creare un Client di posta
Volete costruirvi un client di posta? Volete costruire una Web Mail ? Ecco un articolo che vi introduce al protocollo POP3 e vi insegna come costruire un mini client di posta elettronica.
Autore: Giovanni Ferron | Difficoltà: | Commenti: 2 | Voto:
La stampa di una Win Form
Vedremo in questo articolo i passi necessari per creare una stampa sia di testo che di grafica di una WinForm attraverso .NET.
Autore: Marco Caruso | Difficoltà: | Commenti: 9 | Voto:
Creare un Setup di un progetto con Visual Studio .NET
Ecco delle semplici ma dettagliate istruzioni passo-passo per costruire un pacchetto di Setup (Setup Package) per le nostre Applicazioni WinForms.
Autore: Marco Caruso | Difficoltà: | Commenti: 18
Creare un?icona nella Taskbar di Windows con .NET
Scoprirete come potenziare la vostra applicazione aggiungendo un'icona nella barra di Windows nella famosa Tray Area a fianco dell'orologio del sistema. Disponibile sia codice VB.NET che C#.
Autore: Giovanni Ferron | Difficoltà: | Commenti: 1 | Voto:
Costruire un Servizio di Windows usando .NET
Un avanzato tutorial che vi spiegherà passo passo e in modo dettagliato le istruzioni per costruire un Servizio Windows, utilizzando ciò che il .NET Framework ci mette a disposizione. Disponibile sia codice C# che VB.NET.
Autore: Giovanni Ferron | Difficoltà: | Commenti: 13 | Voto:
Windows XP Visual Styles con .NET e Win Forms
Come usare lo stile XP nelle vostre applicazioni .NET ? Questo articolo vi spiega come applicare a Buttons, Textbox, ListViews (ai controlli di Windows in genere) lo stile/tema grafico della GUI introdotto dal sistema operativo Windows XP.
Autore: David De Giacomi | Difficoltà: | Commenti: 7
Come sfruttare le funzioni di una DLL unmanaged esterna creata in C/C++
Come usare la classe DllImportAttribute messa a disposizione dal namespace System.Runtime.InteropServices per sfruttare le funzioni di una DLL unmanaged Win32 old-style scritta con Visual C++ 6.0
Autore: David De Giacomi | Difficoltà: | Commenti: 4 | Voto:
Creare una DLL in Visual C++ 6.0
Vedremo in questo articolo come creare una Dynamic Link Link Library, comunemente chiamata DLL con Visual C++ 6.0. Questo passo è necessario per poi dimostrare l'utilizzo di librerie C/C++ in .NET tramite il package System.Runtime.InteropServices
Autore: David De Giacomi | Difficoltà: | Commenti: 11 | Voto:
Copyright © dotNetHell.it 2002-2017
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5