[sqlexpress+vs2008+immagini] Come procedere?

mercoledì 19 maggio 2010 - 21.00

xenical73 Profilo | Newbie

vorrei realizzare un db con sqlexpress in cui poter popolare alcuni campi con file di immagini e poi poter visualizzare tali immagini all'interno di una webform realizzata con VS 2008 in VB.

Come posso procedere?

Grazie

alx_81 Profilo | Guru

>vorrei realizzare un db con sqlexpress in cui poter popolare
>alcuni campi con file di immagini e poi poter visualizzare tali
>immagini all'interno di una webform realizzata con VS 2008 in VB.
>Come posso procedere?
posso dirti come la penso lato database, poi per il resto è normale VB.
Non sono un estimatore dei campi LOB (come text, image, che oltretutto verranno deprecati nelle prossime versioni di sql server).
Di conseguenza sono per creare una folder in cui salvare i file, fare un campo che corrisponde al path del file e scrivere solo il path su db, come stringa.
Ovviamente poi devi fare attenzione a gestire l'upload del file e tutti quei casi in cui il campo è stato scritto ma il file no, ecc.. insomma, creare una transazione applicativa (ma è una scelta) per fare "TUTTO O NIENTE".

Per step
- creazione cartella
- procedura db che scrive il campo path (insert o update)
- procedura vb che scrive il file su serve nella cartella creata
- eventuale transazione che tiene unita la scrittura su db e l'upload su server

in lettura poi, la source path dei tuoi controlli immagine sarà il campo path e con esso punterai alla cartella con i file.

>Grazie
di nulla!
--

Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi

alexmed Profilo | Guru

Scusate l'intromissione ma vorrei dare un consiglio e chiedere delucidazioni in quanto stò affrontando lo stesso problema.

Prima il consiglio:
In fase di copiatura del file dalla cartella locale a quella server rinominare il file immagine in base alla data ed ora in cui avviene la copia.
Questo eviterà che la procedura si pianti perchè esiste già un file con nome uguale nella cartella di destinazione.

Questo è il codice che uso:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Il problema invece è come essere sicuri che sia la INSERT nel db che la copia vadano a buon fine entrambe.
Suggerimenti?

alexmed

alx_81 Profilo | Guru

>Scusate l'intromissione ma vorrei dare un consiglio e chiedere
>delucidazioni in quanto stò affrontando lo stesso problema.
intromissione? più siamo e meglio è

>Prima il consiglio:
>In fase di copiatura del file dalla cartella locale a quella
>server rinominare il file immagine in base alla data ed ora in
>cui avviene la copia.
>Questo eviterà che la procedura si pianti perchè esiste già un
>file con nome uguale nella cartella di destinazione.
ok, a meno che tu non voglia proprio che si pianti se il nome è lo stesso. Mi è capitato di dover legare un'entità col nome del file e, per vincolo, fare in modo che venisse restituito l'errore nel caso in cui si trattasse della stessa entità, comunque il consiglio è validissimo.

>Il problema invece è come essere sicuri che sia la INSERT nel db che la copia vadano a buon fine entrambe.
>Suggerimenti?
transazione applicativa.. Quando apri la connessione ti fai anche la transazione e gestisci commit e rollback dall'applicazione. Sarà potenzialmente lunga, lockera parte della tabella per molto tempo, ma se necessario, puoi usare quel metodo. Attenzione però ai lock.
--

Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi

alexmed Profilo | Guru


>intromissione? più siamo e meglio è

>ok, a meno che tu non voglia proprio che si pianti se il nome
>è lo stesso. Mi è capitato di dover legare un'entità col nome
>del file e, per vincolo, fare in modo che venisse restituito
>l'errore nel caso in cui si trattasse della stessa entità, comunque
>il consiglio è validissimo.
Il metodo File.Copy (String, String) in effetti solleva un'eccezione se trova un file di destinazione con lo stesso nome.

>transazione applicativa.. Quando apri la connessione ti fai anche
>la transazione e gestisci commit e rollback dall'applicazione.
>Sarà potenzialmente lunga, lockera parte della tabella per molto
>tempo, ma se necessario, puoi usare quel metodo. Attenzione però
>ai lock.
>--
commit, rollback, lock ... ... è qui che casca l'asino!!!
Se hai dei link per capire meglio sono sempre pronto ad imparare.

Grazie


alexmed

xenical73 Profilo | Newbie

Caro alessandro

se per alexmed casca l'asino...per me masca l'everest

Io sono veramente alle prime armi nel campo db/asp

ho realizzato qualche db e webform con formview per lettura dati...usando anche le procedure guidate di VS.

Da come scrivete qui mi pare che la cosa si complichi un pochino (per voi sarà una banalità..per me no però ...ma sono dispostissimo ad imparare).

Quindi andiamo per ordine:

- creazione cartella (fin qui ci arrivo )

- procedura db che scrive il campo path (insert o update):
Guardando in sqexpress nei vari "tipi di dati" il valore path non esiste (mentre esiste image); che tipo di dato dovrei usare?
Per le funzioni insert e update dei dati nel db io ho sempre usato le procedure guidate di vs
quindi qui inizia già il marasma

So che starai pensando..ma se nn sai ste cose cosa pretendi di fare?

alexmed Profilo | Guru

Ciao
Provo a risponderti io.
Per prima cosa devi decidere come organizzare il lavoro, su come vuoi archiviare le foto.
Le soluzioni che mi vengono subito in mente sono:
1. Mettere tutte le foto (immagini) dentro una cartella (es. \\miopercorso\Immagini\)
In questo caso nella colonna del database (che sarà ti tipo nvarchar(50)) ospiterà solo ed esclusivamente il nome dell'immagine (quindi "IMG_000.JPG").
Quando dovrai richiamare la foto per visualizzarla nella PictureBox andrai a combinare il percorso (che sarà costante, \\miopercorso\Immagini\) con il nome della img prelevata dal db
2. Organizzare le immagini dentro delle cartelle che creerai al momento che magari si riferiscono all'ID della foto stessa.
Quando le dovrai richiamare combinerai il percorso (\\miopercorso\Immagini\) con l'ID della foto e con il nome della img salvato nel db.
3. Le foto si trovano in cartelle già esistenti e non puoi muoverle.
In questo caso nella colonna andrai a salvare il percorso completo dell'img
(es. C:\Documents and Settings\Administrator\Documenti\Immagini\IMG_000.JPG)

Ciao

alexmed

alx_81 Profilo | Guru

>Da come scrivete qui mi pare che la cosa si complichi un pochino (per voi sarà una banalità..per me no però ...ma sono dispostissimo ad imparare).
non è una banalità ed è sempre stato un annoso problema.

cerchiamo di fare chiarezza un po' su tutto..
Diciamo che fondamentalmente ci sono tre strade:

1) campo BLOB (Binary Large Object) che contiene il binario dell'immagine (ovvero l'immagine).
In questo modo in asp ad esempio, basta fare una Response.BinaryWrite del campo blob ed il gioco è fatto:
pro:
tutto su db e quindi anche i backup si portano i file caricati
transazione monolitica (non devo preoccuparmi del filesystem)
facilità di lettura (è un campo su tabella)

contro:
notevole appesantimento sul db e del backup
possibilità di lettura non posizionale (ad esempio una select su tutte le righe) lentissima
incremento della grandezza (in termini di tempo) della transazione

2) campo path (di tipo varchar(300) ad esempio, path non esiste, è proprio stringa) che punta ad una cartella fisica.
Quando si va a leggere il file, si passa dal campo che contiene il path e si punta al file

pro:
database non trasformato in file storage
database più leggero
possibilità di usare spazio alternativo su disco

contro:
possibile desincronizzazione (se il secondo dei due processi va male e non è stata prevista la transazione che ti consente il TUTTO O NIENTE, potresti aver fatto un'operazione e l'altra no).
il backup del database porta con sè solo il percorso, ma lascia ovviamente il file dove sta
siccome è possibile una desincronizzazione (non faccio transazione oppure un user cancella un record direttamente su db o ancora un utente cancella un file per errore, ecc) si è costretti ad una gestione dell'errore custom con tutte le casistiche.

3) FileStream (http://msdn.microsoft.com/it-it/library/bb933993.aspx), funzionalità di sql server 2008
pro:
database non trasformato in file storage ma che gestisce in automatico uno storage separato
transazione implicita
possibilità di usare spazio alternativo su disco
permette uno storaggio che va oltre i campi blob old style (text, image)

contro:
va abilitato

Da questo potete capire che in ognuno dei casi, se il file è pesante, la transazione (ovvero l'unità di lavoro del database) diventa decisamente impegnativa. Una transazione impegnativa potrebbe tenere bloccata parte della tabella per molto tempo, e chiunque cerchi di accedere, anche in lettura (con l'accesso pessimistico di default - leggo solo se nessuno ha preso in carico quel record), potrebbe dover aspettare tanto.
Questo potrebbe portare a rallentamenti indesiderati. Inoltre, se si sceglie il punto 2), siamo costretti a fare una transazione direttamente da codice: http://msdn.microsoft.com/it-it/library/system.data.sqlclient.sqltransaction(VS.80).aspx. Questo perchè non avendo il controllo su database, si è costretti a spostarsi sul codice (iniziare la transazione, elaborare, committare o fare rollback).
Spero di essere stato più chiaro, anche se queste cose meriterebbero tanto tempo in più..

--

Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi

xenical73 Profilo | Newbie

Per quanto riguarda l'organizzazione del lavoro ci sono.

per le funzioni insert/update di cui parlava alessandro? posso usare quelle che ho usato fino ad ora di vs?

alx_81 Profilo | Guru

>per le funzioni insert/update di cui parlava alessandro? posso
>usare quelle che ho usato fino ad ora di vs?
se leggi attentamente quanto ho scritto, noterai che quelle di default non ti danno grandi possibilità..
Ti dovrai guardare un po' di ado.net..

--

Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi

xenical73 Profilo | Newbie

Da quello che scrivi opterei per la soluzione 2 in quanto la 1 effettivamente dopo un pò di utilizzo genererebbe DB grandi e pesanti e escluderei la 3 visto che nn ho la versione pro di sql
Inoltre la webform e relativo db verrebbe usato in locale da 1 singolo utente.

ora vedo cosa riesco a combinare.

Grazie mille

xenical73 Profilo | Newbie

magari sto per dire un avaccata immane...ma picture box nelle webform non esistono...sono solo per winform

alexmed Profilo | Guru

Quando ti ho risposto stavo pensando alla mia applicazione.
Non c'è la PictureBox ma ci sono le <asp:Image> oppure le HTML <img>

Ciao

alexmed

xenical73 Profilo | Newbie

Vista la mia scarsa dimestichezza nel settore...

ma io volevo (ammesso che si apossibile) creare un db (faccio un esempio semplice):

ID int
Immagine nvarchar (max) [per inserire la path dell'immagine]
Descrizione nvarchar(max) [per inserire una descrizione dell'immagine].

Realizzare poi una webform in cui inserire una formview in cui recuperare l'immagine ID e descrizione

Quanto mi avete descritto prima (che nn ho ancora capito come poter realizzare) e da quanto son riuscito a trovare in rete si tratterebbe solo di una gestione delle immagini (usando appunto asp image)

alexmed Profilo | Guru

Ciao
Una volta creato il database con la tabella impostata come hai detto devi semplicemente trascinare sulla pagina due controlli:
Il primo è il <asp:SqlDataSource> al quale configurerai, tramite procedura guidata, il tuo database e quindi la tabella Immagini.
Il secondo è un <asp:FormView> (ad esempio) al quale devi associare il <asp:SqlDataSource>.
In automatico ti creerà i campi della tabella Immagini.
Ti creerà una parte che si chiama ItemTemplate che al suo interno ha un controllo <asp:Label> con il relativo riferimento alla colonna con il nome dell'immagine.
A questo punto inserisci un controllo <asp:Image> al quale devi associare il percorso ed il nome della immagine:

<asp:Image ID="Image1" Width="640px" runat="server" ImageUrl='<%# "img/" & Eval("Fotografia") %>' />

Io ho usato un FormView ma nulla ti impedisce di utilizzare altri controlli.

Ciao

alexmed

alexmed Profilo | Guru

Mi son dimenticato che magari puoi anche dare una veloce lettura qui:
http://www.w3schools.com/aspnet/aspnet_pages.asp
alexmed

xenical73 Profilo | Newbie

Io avevo fatto questo :

"Una volta creato il database con la tabella impostata come hai detto devi semplicemente trascinare sulla pagina due controlli:
Il primo è il <asp:SqlDataSource> al quale configurerai, tramite procedura guidata, il tuo database e quindi la tabella Immagini.
Il secondo è un <asp:FormView> (ad esempio) al quale devi associare il <asp:SqlDataSource>.
In automatico ti creerà i campi della tabella Immagini.
Ti creerà una parte che si chiama ItemTemplate che al suo interno ha un controllo <asp:Label> con il relativo riferimento alla colonna con il nome dell'immagine."


e ovviamente non mi compariva l'immagine ma solo la stringa...
ora provo come mi hai suggerito

"A questo punto inserisci un controllo <asp:Image> al quale devi associare il percorso ed il nome della immagine:

<asp:Image ID="Image1" Width="640px" runat="server" ImageUrl='<%# "img/" & Eval("Fotografia") %>' />"

Grazie

alexmed Profilo | Guru

Naturalmente il controllo asp:Image deve essere collocato all'interno dell'ItemTemplate

alexmed

xenical73 Profilo | Newbie

Ci sono quasi..c'è ancora una cosa che non mi torna perchè l'immagine non viene visualizzata nel browser (sarà un errore da qualche parte)

questo è il codice

<ItemTemplate> ID: <asp:Label ID="IDLabel" runat="server" Text='<%# Eval("ID") %>' /> <br /> Immagine: <asp:Label ID="ImmagineLabel" runat="server" Text='<%# Bind("Immagine") %>' /> <asp:Image ID="Image1" runat="server" ImageUrl='<%# Eval("Immagine") %>' /> <br /> Descrizione: <asp:Label ID="DescrizioneLabel" runat="server" Text='<%# Bind("Descrizione") %>' /> <br /> <asp:LinkButton ID="EditButton" runat="server" CausesValidation="False" CommandName="Edit" Text="Modifica" /> &nbsp;<asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False" CommandName="Delete" Text="Elimina" /> &nbsp;<asp:LinkButton ID="NewButton" runat="server" CausesValidation="False" CommandName="New" Text="Nuovo" /> </ItemTemplate>

Ma nel browser rimane un'iconcina senza mostrare la foto (NB: non icona con croce rossa)

alexmed Profilo | Guru

Potrebbe dipendere da cosa hai registrato nel campo della tabella.
Se tutto il percorso dove sono le immagini oppure se solo il nome dell'immagine:
Nel primo caso allora il codice sembra corretto, nel secondo devi anteporre il percorso

Quindi, supponendo che le tue immagini siano all'interno della cartella "img" dovrai scrivere:

ImageUrl='<%# "img/" & Eval("Immagine") %>'

Ciao

alexmed

xenical73 Profilo | Newbie

C'è tutto il path comprensivo di nome file

infatti son qui che mi sto scervellando e nn riesco a capire dove sia l'inghippo

alexmed Profilo | Guru

Tutto il path scritto come?

C:\Documents .....
Oppure
/img/

alexmed

xenical73 Profilo | Newbie

Nel campo "immagine" del DB ho riportato tutto il path relativa all'immagine in questione

C:\Lavoro\Clienti\xxxxxx\Gestionale\Immagini\01.bmp (e così per tutte le altre)

alexmed Profilo | Guru

Il problema è lì, nel percorso.
Quando esegui l'applicazione, nonostante sia in locale il percorso principale dipende dal LocalHost quindi una cosa tipo:

http://localhost:57881/.../Default.aspx

Prendi la cartella delle immagini e spostala all'interno della soluzione (il sito) ed elimina la parte di percorso (C:\Lavoro\Clienti\xxxxxx\Gestionale) dal campo della tabella.

Credo, in ambiente WebApplication, che non si possa far riferimento al disco C:\.

alexmed

xenical73 Profilo | Newbie

Perfetto..funziona.

Ora devo gabulare come fare per l'upload, modifica ed eliminazione, perchè credo che i 3 coandi che ho creato (utilizzando i template di vs) nn svadano bene per le immagini )o mi sbaglio)?

alx_81 Profilo | Guru

>Ora devo gabulare come fare per l'upload, modifica ed eliminazione,
>perchè credo che i 3 coandi che ho creato (utilizzando i template
>di vs) nn svadano bene per le immagini )o mi sbaglio)?
I comandi di default ti permettono poco.
però puoi leggere qui per capire meglio come funziona l'upload:
http://www.dotnethell.it/tips/UploadFilesASPNET.aspx

è in c#, ma è facilmente riconducibile a vb.net
puoi dare un'occhiata anche qui
http://www.developer.com/net/asp/article.php/3689276/File-Upload-with-VBNET.htm

--

Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi

alexmed Profilo | Guru

Ok, allora direi di fare così: qui chiudi il post ed eventualmente altri, aprili nella stanza dedicata ad ASP o HTML
Ciao

alexmed

alx_81 Profilo | Guru

>Ok, allora direi di fare così: qui chiudi il post ed eventualmente
>altri, aprili nella stanza dedicata ad ASP o HTML
>Ciao
e magari accetta la risposta ad alexmed che si è impegnato a seguirti per bene

--

Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi

xenical73 Profilo | Newbie

Fatto

Grazie mille per l'aiuto
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5