venerdì, aprile 11, 2008

SqlDataSource, recuperare l'identità appena inserita

Quando si esegue un INSERT INTO attraverso le funzionalità dell'oggetto SqlDataSource, magari collegato a un FormView, può essere molto utile risalire alla chiave appena inserito nella tabella.
Ovviamente mi riferisco a una tabella che abbia come campo chiave un identità.
Ecco come fare:
impostare InsertCommand del SqlDataSource in questo modo

INSERT INTO [TABELLA] ([CAMPI])
VALUES ([@PARAMETRI]);SELECT
@NewID=SCOPE_IDENTITY()

Aggiungere fra gli InsertParameter:
Name="NewID" Direction="OUTPUT" Type="Int32"

Ora, nell'evento Protected Sub SqlDSClient_Inserted è possibile recuperare il valore:
e.Command.Parameters("@NewID").Value

Etichette:


giovedì, aprile 10, 2008

Anche A.Einstein faceva il programmatore?

La teoria è quando si sa tutto e non funziona niente. La pratica è quando
funziona tutto e non si sa perchè.

Bene o male riusciamo sempre a coadiuvare le
2 cose e non funziona niente e non sappiamo il perchè.


Anche A.Einstein faceva il programmatore?



mercoledì, aprile 09, 2008

Asp.Net file Download Confirmation

Per verificare che il client scarichi completamente un file dal vostro server, è necessario implementare una pagina di passaggio che legga lo stream del file e lo invii al client.
Durante l'invio è sufficiente verificare che la proprietà Response.IsClientConnected rimanga a True per tutto il tempo necessario.
Ecco un esempio:


Response.Clear()
Dim b(1024 * 128) As Byte
Dim DownLoadAbort As Boolean = False
Dim f As IO.FileStream = New IO.FileStream("c:\filename.txt", IO.FileMode.Open)
Response.AddHeader("Content-Disposition", "attachment;filename=filename.txt")
Response.AddHeader("Content-Length", f.Length.ToString)
Do While f.Position < f.Length
f.Read(b, 0, 1024 * 128)
Response.OutputStream.Write(b, 0, 1024 * 128)
If Not Response.IsClientConnected Then
DownLoadAbort = True
Exit Do
End If
Response.Flush()
Loop
f.Close()

If Not DownLoadAbort Then
'DOWNLOAD COMPLETED SUCCESFULLY
Else
End If
Response.End()


lunedì, aprile 07, 2008

Importazione di File excel, scoprire la struttura e i nomi dei fogli

Per accedere al contenuto dei file Microsoft Excel ci si può molto semplicemente appoggiare all'oggetto data.OledDbConnection

Dim strConn As String = "Provider=Microsoft.Jet.OLEDB.4.0;" &
"Data Source=c:\fileexcel.xls; Extended Properties=Excel
8.0;"
'Connect to the file source
Dim conn As New
System.Data.OleDb.OleDbConnection(strConn)


E per leggere il contenuto:


Dim myData As New Data.OleDb.OleDbDataAdapter("SELECT * FROM [foglio1$]",
strConn)
myData.Fill(myDataset)


E se ora volessimo visualizzare il contenuto in un gridview:

GridView1.DataSource = myDataset.Tables(0).DefaultView
GridView1.DataBind()

Il vero problema è che non sempre si conosce la struttura esatta del file excel, soprattutto quanti fogli (worksheet) ci sono e il loro nome, importante per poter effettuare la SELECT dei dati.
Un approccio potrebbe essere quello di utilizzare gli oggetti .Net per accedere al framework COM di office, soluzione svantaggiosa, obbligherebbe ad avere Office installato sulla macchina, e se si tratta di un web server, potrebbe essere un serio problema.
Approccio più efficace è l'uso delle potenzialità di analisi della struttura di database della OledDBConnection, attraverso il metodo GetOleDbSchemaTable.
In particolare dopo aver aperto la connessione al file excel:

Dim SchemaTable As Data.DataTable
conn.Open()
SchemaTable = conn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, New
Object() {Nothing, Nothing, Nothing, Nothing})
conn.Close()

e quindi analizzando lo schema:

Dim fogli As New Generic.List(Of String)
For Each row As DataRow In SchemaTable.Rows
    If row!TABLE_TYPE.ToString = "TABLE" Then
        fogli.Add(row!TABLE_NAME.ToString())
    End If
Next

Ecco ottenuto l'elenco dei fogli.

Per approfondire sull'argomento, consiglio: How To Retrieve Schema Information by Using GetOleDbSchemaTable and Visual Basic .NET http://support.microsoft.com/kb/309488/en-us

venerdì, aprile 04, 2008

Asp.Net Ajax file Download

Ajax dona grandi vantaggi in termini di navigabilità, interattività e user experience alle vostre applicazione web.
Uno dei fattori che è spesso sottovalutato è la diminuzione del traffico generato dalle pagine, in quanto solo una piccola parte della pagina viene inviata dal server al browser.
In pratica evita di dover inviare ogni volta un documento intero, ma solo una parte.

Di contro, quando ci si trova a dover inviare un documento completo al browser, soprattutto se generato a runtime, sorgono dei problemi.
Se ad esempio nell'evento click di un bottone si genera un file excel

response.ContentType = "application/vnd.ms-excel"
response.AddHeader("Content-Disposition", "attachment; filename=report.xls")
response.write ...
response.end

Alla pressione del bottone il broser restituirà un messaggio di errore abbastanza chiaro:
Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, HttpModules, or server
trace is enabled.

Stiamo inviando al browser qualcosa di inadatto al contesto.
Fortunatamente aggirare il problema è abbastanza semplice:
registrando nei trigger del nostro UpdatePanel un nuovo PostBackTrigger collegato al nostro bottone di download
<asp:updatepanel id="UpdatePanel1" runat="server">
<triggers>
<asp:postbacktrigger controlid="ControlID">
</triggers>
Se invece il vostro controllo fosse generato a runtime, (es: un bottone inserito in GridView) sarà necessario effettuare al registrazione a runtime, dopo che il controllo è stato generato:

ScriptManager.GetCurrent(Page).RegisterPostBackControl(ImageButton1)

Etichette:


giovedì, aprile 03, 2008

Sql server, concatenare una riga in una colonne

Capita spesso di avere la necessità di estrarre dal database un elenco formato dalla concatenazione delle righe risultanti una query.
Per esempio gli accessori di un veicolo, le sottocategorie di una macrocategoria,ecc.

Invece di estrarre il recordset e ciclare riga per riga o invece di usare un cursore si può molto più rapidamente:


declare @property AS varchar(2000)
select @property = COALESCE(@property, '') + description_it + ','
from vwCATPROP where idcategory=1
select @property as property
Ed ecco il risultato:




#