Help Su connection a DB access e uso DataGrid

venerdì 20 marzo 2009 - 11.12

Andrew78 Profilo | Newbie

Ciao a tutti i forumendoli di .NetHell.it...
Vi descrivo il mio problema, premetto che ho da poco scoperto il mondo di VisualStudio per motivi lavorativi, e sto tentando di costruire un'applicazione web (asp.net) col quale accedo a un semplice DB Access e poi visualizzare i risultati in una datagrid.
Ho utilizzato una OleDbConnection per accedere al DB (provider Ole DB: Microsoft Jet 4.0 Ole DB Provider) dopodichè ho usato un OleDbDataAdapter per effetuare una semplice Select * from tabella, ho successivamente creato il DataSet (nella preview tira fuori correttamente i dati).
Dopodichè ho inserito un datagrid e come DataSource ho messo il Data Set creato, infine ho inserito il comando

OleDbDataAdapter().Fill(DataSet31)

nel button_click. Tutto ok fin qui, tranne quando lancio l'applicazione e a browser mi compare il bottone, una volta cliccato non succede niente. Non ricevo nemmeno un messaggio di errore. Com'è possibile?...dov'è che sto sbagliando?...oppure mi sono dimenticato qcosa?...

Grazie in anticipo!!!....

ysdemarc Profilo | Expert

ma nel post dove sta il datagrid?

comunque la tua fonte dati se tutto è corretto la dovresti associare al datagrid in questo modo:

myDataGrid.DataSource = DataSet31;
myDataGrid.DataBind(); //<---- indispensabile altrimenti non fa il binding e non vedi nulla.

ciao
Vincenzo
Programmatore sbilenco

Andrew78 Profilo | Newbie

Grazie per la dritta!

Ho risolto così:
DataGrid.DataSource = DataSet31
OleDbDataAdapter.Fill(DataSet31)
DataGrid.DataBind()

e ora mi riempe correttamente i campi del datagrid...facendo come dicevi te mi faceva vedere solo l'intestazione del datagrid ma non la riempiva.
A questo punto avrei un'altra domanda, perchè il datagrid non fa il sorting delle colonne e non va avanti e indietro nella navigazione pur avendo abilitato il sorting e il paging?
Ti ho allegato uno screenshot


802x571 63Kb


Cmq grazie in anticipo!!!....

ysdemarc Profilo | Expert

credo che non te li faccia poichè nono avrai programmato gli eventi SortCommand e PageIndexChanged

ad esempio:

private void DataGrid1_PageIndexChanged(object source, System.Web.UI.WebControls.DataGridPageChangedEventArgs e)
{
DataGrid1.CurrentPageIndex = e.NewPageIndex;
DataBiding();

}
//qui sorti e fai il binding
private void DataBiding()
{
DataTable dt = miafontedati;
DataView dv = new DataView(dt);
dv.Sort = "MIOCAMPO DESC";
DataGrid1.AllowSorting = true;
DataGrid1.DataSource = dv;
DataGrid1.DataBind();
}

A quanto ho compreso, Il datagrid non è intelligente che fa tutto da solo, anche perchè dopo che hai passato la prima pagina al client, il server non ha più idea di cosa sia successo e quindi glielo devi ricordare..

in pratica se usi la paginazione ti consiglierei di mettere la tua fonte dati, dopo la prima estrazione in Session, altrimenti ti ritrovi a fare accessi al database ad ogni clic utente.

Se la mole dei dati è grande, alla prima richiesta l'utente rischia di andare in pensione prima di avere la pagina successiva e forse solo i nipoti riusciranno a vedere la richiesta.

In genere, io faccio nel modo seguente.

Mi costruisco una bella classettina che mi estrae i dati e mi restituisce un datatable
Nelle queries della classe di estrazione mi gestisco le paginazioni con sql, così da estrarre sempre e solamente le righe necessarie ed evitare lavoro inutile al db.
Magari all'utente interessa solo vedere un dato di tutti quelli che estrai...estrarli tutti mi sembra solo darsi zappate ai piedi col rischio enorme di timeout.
e quindi se l'utente vuole andare alla pagina successiva mi prendo l'ultimo valore di chiave letto e la stringa sql parte dal valore successivo in poi.. e straendo solo il numero di record della paginazione..e così via.. e naturalmente per tornare indietro prendo la chiave della prima riga del datagrid e leggo da quella in poi in ordine decrescente...

magari quest'approccio sarà discutibile..ma è l'unico con cui ho potuto velocizzare la visualizzazione dei dati...
Vincenzo
Programmatore sbilenco

Andrew78 Profilo | Newbie

Ok...ho capito cosa intendi...però non ho trovato nei toolbox DATA l'oggetto datatable...ho trovato il dataview...ho provato a fare add/remove items ma non ho trovato niente......l'oggetto table in Web Forms potrebbe andare bene?
Ah...dimenticavo, ho da farti un'altra domanda...prometto che è l'ultima...ma se volessi aggiungere o togliere un record....come dovrei procedere?

Grazie 1000!!!!....

ysdemarc Profilo | Expert

il tuo DataSet31 contiene una collezione di DataTable..

se la tua query di partenza è una solo lo trovi con l'indice 0.

cosa intendi per aggiungere o togliere una riga?

se si tratta di visualizzare o meno una riga dovresti gestirla o con la tua stringa sql oppure nell'evento DataBinding del controllo dataGrid.

Se intendi far inserire, eliminare o modificare le righe, le potresti fare, nel primo caso con un modulo con controlli text e quant'altro reputi necessario per tutti gli altri casi inserendo le colonne pulsanti appropriate che trovi nella finestra delle proprietà...

da quello che mi scrivi penso che ti hanno messo davanti sto controllo senza sapere ben molto.. prova a dare un'occhiata alla guida di visual studio.. dovresti trovare anche qualche esempio che ti può interessare...
Vincenzo
Programmatore sbilenco

Andrew78 Profilo | Newbie

Grazie per le dritte!...si in effetti so ben poco di tutto.......

Private Sub DataGrid_PageIndexChanged(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridPageChangedEventArgs) Handles DataGrid.PageIndexChanged
'DataGrid.CurrentPageIndex = e.NewPageIndex
'OleDbDataAdapter.Fill(DataSet31)
'DataGrid.DataBind()
DataGrid.CurrentPageIndex = e.NewPageIndex
DataBinding1()
End Sub

Private Sub DataBinding1()
Dim dt As DataTable
Dim dv As DataView
dt = DataSet31.Tables(0)
dv = New DataView(dt)
DataGrid.AllowSorting = True
DataGrid.DataSource = dv
DataGrid.DataBind()
End Sub

Ti spiego subito...in DataGrid_PageIndex le tre righe commentate mi consentono di navigare nel DataGrid ma accede direttamente al db...ho provato (il resto del codice) a fare come dici te ma mentre tento di navigare nel datagrid mi resituisce il seguente errore che vedi in allegato


1057x601 106Kb


Cmq si, intendo far inserire, eliminare o modificare le righe.
Non riesco però a capire cosa intendi quando dici: " le potresti fare, nel primo caso con un modulo con controlli text e quant'altro reputi necessario per tutti gli altri casi inserendo le colonne pulsanti appropriate che trovi nella finestra delle proprietà..."

Tieni presente che uso VisualStudio 2003 e asp.net 1.0/1.1....

ysdemarc Profilo | Expert

temo che tu stia facendo una grandissima confusione..
Prima di ogni cosa devi sapere che la programmazione web è diversa da quella pc.. quindi una variabile globale non dura per la durata dell'applicazione ma solo per la durata della pagina fino a che non fai un postback.
Quindi se ti servono valori da passare tra le pagine, potresti in caso usare le Session.
allora andiamo per punti fino all'estrazione dati ci siamo giusto?

tu sai che i dati (dataset, datatable, dataview) li devi passare al metodo DataSource del controllo DataGrid e fare la bind.

per cui se usi le paginazioni qualcosa di buono potrebbe essere questo:

//dichiaro una variabile di tipo Datatable da passare al datasource (potrebbe anche essere dataset ecc...
private DataTable dt = null;

private void Page_Load(object sender, System.EventArgs e)
{
if (!IsPostBack) //se non è un postbackk e quindi entro per la prima volta nella pagina
{
dt = GetFonteDati(); //GetFonteDati() è la funzione che fa gli accessi al db e dovrebbe restituirmi un datatable
}
else
{ //tutte le volte succressive
dt = (DataTable)Session["mio.dt"];
}
DataBinding();
}
private void DataBinding()
{
DataGrid1.DataSource = dt;
DataGrid1.DataBind();
}

facciamo finta che la mia select comprenda un campo chiave, uno descrizione e un quantità di una certa tabella...

io quindi voglio abilitare le paginazioni e permettere le modifiche..per cui vado in proprietà --> generatore di proprietà del datagrid
e imposti le colonne..da li inserisci pure i pulsanti per la modifica..e quant'altro vuoi.

Dalle proprietà imposto Allowpage = true e pagesize = 5

e scrivo l'evento:
private void DataGrid1_PageIndexChanged(object source, System.Web.UI.WebControls.DataGridPageChangedEventArgs e)
{
DataGrid1.CurrentPageIndex = e.NewPageIndex;
DataBinding();
}

e così via..avrai altri eventi a disposizione come DeleteCommand, EditCommand..

ti rimando ad una guida tipo: http://www.webmasterpoint.org/guida-asp-net/datagrid-editable_a56.html (in vb.net)

Ora l'errore che di dava a te era perchè dopo che clicci sul next del controllo per visualizzare gli altri record, ti perdi la tua fonte dati, che invece, per evitare accessi al db potresti gestirti con la session..e comunque ad ogni ricarico pagina devi associare la fonte dati e fare la bind

Per l'inserimento io intendevo moduli web creati in un'latra pagina, tanto per avere il controllo..e ancor che (a parte che non so se dal datagrid si possono fare inserimenti exnovo..anche se tutto si può fare..basta volerlo) non è bello fare scrivere all'utente nella griglia..

per cui una pagina dedicata apposta.. niente di arcano...

ciao
Vincenzo
Programmatore sbilenco

Andrew78 Profilo | Newbie

Ok...andiamo x gradi...
Pe quanto riguarda la prima parte (il codice lo sto scrivendo in VB) ho fatto una cosa del genere:

Public Class WebForm1
Inherits System.Web.UI.Page
Private dt As DataTable //variabile datatable da passare al data source

#Region " Web Form Designer Generated Code "

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
If Page.IsPostBack = False Then
dt = DataSet31.Tables(0) //dovrebbe essere la mia fonte dati giusto?
Else
dt = Session. //non saprei come scrivere quello che intendi te cioè: dt = (DataTable)Session["mio.dt"];
End If
DataGrid.DataBind()
End Sub

Come sempre, Grazie!!!....

ysdemarc Profilo | Expert

scusa..ho sbagliato anch'io a scrivere..
provo a scriverlo in vb..

private sub Page_Load(sender as object, e as System.EventArgs)

If Not IsPostBack Then

dt = GetFonteDati();
Session.Add("mio.dt", dt); //<-- avevo scordato questo

else
dt = DirectCast(Session("mio.dt"), DataTable)


End If
DataBinding()

end sub

Vincenzo
Programmatore sbilenco

Andrew78 Profilo | Newbie

Ho provato a fare così:

Public Class WebForm1
Inherits System.Web.UI.Page
Private dt As DataTable

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
If Page.IsPostBack = False Then
dt = DataSet31.Tables(0) <--- E' la mia fonte dati giusto?
Session.Add("mioDt", dt)
Else
dt = DirectCast(Session("mioDt"), DataTable)
End If
OleDbDataAdapter.Fill(dt) <---Senza il fill e poi la bind non estrae....ho provato a mettere solo DataBinding() oppure Binding() ma niente
DataGrid.DataBind() <----quindi ho fatto così....prima il fill e poi il metodo del datagrid...
End Sub

Private Sub DataGrid_PageIndexChanged(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridPageChangedEventArgs) Handles DataGrid.PageIndexChanged
DataGrid.CurrentPageIndex = e.NewPageIndex
OleDbDataAdapter.Fill(dt)
DataBind()
end sub

end class


quando lancio l'applicazione mi compare il datagrid con i primi record, ma quando navigo alla seconda pagina del datagrid mi compare una riga con scritto 1, come ti ho messo nello screenshot

1055x590 46Kb


ysdemarc Profilo | Expert

ma cosa c'entra OleDbDataAdapter.Fill(dt) in quella posizione?

ma come estrai i dati?

posta il codice con cui fai l'estrazione..
Vincenzo
Programmatore sbilenco

Andrew78 Profilo | Newbie

Ecco il codice, la region è generata in automatico dai wizard che ho usato per fare la connessione:

#Region " Web Form Designer Generated Code "

'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.OleDbConnection = New System.Data.OleDb.OleDbConnection
Me.OleDbDataAdapter = New System.Data.OleDb.OleDbDataAdapter
Me.OleDbSelectCommand1 = New System.Data.OleDb.OleDbCommand
Me.DataSet31 = New WebApplication2.DataSet3
CType(Me.DataSet31, System.ComponentModel.ISupportInitialize).BeginInit()
'
'OleDbConnection
'
Me.OleDbConnection.ConnectionString = "Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Registry Path=;Jet OLEDB:Database L" & _
"ocking Mode=0;Data Source=""C:\Documents and Settings\Administrator\Desktop\ARCHI" & _
"VIODATI\BIBLIO.MDB"";Mode=Share Deny None;Jet OLEDB:Engine Type=4;Provider=""Micro" & _
"soft.Jet.OLEDB.4.0"";Jet OLEDB:System database=;Jet OLEDB:SFP=False;persist secur" & _
"ity info=False;Extended Properties=;Jet OLEDB:Compact Without Replica Repair=Fal" & _
"se;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Create System Database=False;Jet O" & _
"LEDB:Don't Copy Locale on Compact=False;User ID=Admin;Jet OLEDB:Global Bulk Tran" & _
"sactions=1"
'
'OleDbDataAdapter
'
Me.OleDbDataAdapter.SelectCommand = Me.OleDbSelectCommand1
Me.OleDbDataAdapter.TableMappings.AddRange(New System.Data.Common.DataTableMapping() {New System.Data.Common.DataTableMapping("Table", "Authors", New System.Data.Common.DataColumnMapping() {New System.Data.Common.DataColumnMapping("Au_ID", "Au_ID"), New System.Data.Common.DataColumnMapping("Author", "Author"), New System.Data.Common.DataColumnMapping("Year Born", "Year Born")})})
'
'OleDbSelectCommand1
'
Me.OleDbSelectCommand1.CommandText = "SELECT Au_ID, Author, [Year Born] FROM Authors"
Me.OleDbSelectCommand1.Connection = Me.OleDbConnection
'
'DataSet31
'
Me.DataSet31.DataSetName = "DataSet3"
Me.DataSet31.Locale = New System.Globalization.CultureInfo("it-IT")
CType(Me.DataSet31, System.ComponentModel.ISupportInitialize).EndInit()

End Sub
Protected WithEvents Button1 As System.Web.UI.WebControls.Button
Protected WithEvents OleDbConnection As System.Data.OleDb.OleDbConnection
Protected WithEvents OleDbDataAdapter As System.Data.OleDb.OleDbDataAdapter
Protected WithEvents OleDbSelectCommand1 As System.Data.OleDb.OleDbCommand
Protected WithEvents DataSet31 As WebApplication2.DataSet3
Protected WithEvents DataGrid As System.Web.UI.WebControls.DataGrid
Protected WithEvents Aggiungi As System.Web.UI.WebControls.Button
Protected WithEvents Rimuovi As System.Web.UI.WebControls.Button
Protected WithEvents OutButton As System.Web.UI.WebControls.Button

'NOTE: The following placeholder declaration is required by the Web Form Designer.
'Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object

Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub

#End Region

ysdemarc Profilo | Expert

madò che confusione...

guarda io..non ho mai utilizzato i controlli per le connessioni..dovrei studiarmelo e fare le prove per capire...

in genere io faccio qualcosa del genere:

Private Function GetDati() As DataTable
Dim sql As String = "select * from mionomedb.dbo.miatabella"
Dim connString As String = "Provider=SQLOLEDB.1;Persist Security Info=True;User ID=miauser;Password=miapassword;Initial Catalog=master;Data Source=MIOSERVER\MiaIstanza"
Dim cn As IDbConnection = New OleDbConnection(connString)
Dim cm As IDbCommand = New OleDbCommand(sql, DirectCast(cn, OleDbConnection))
Dim da As DbDataAdapter = New OleDbDataAdapter(DirectCast(cm, OleDbCommand))
Dim cb As OleDbCommandBuilder = New OleDbCommandBuilder(da)
cb.RefreshSchema
Dim ds As DataSet = New DataSet
da.FillSchema(ds, SchemaType.Source)
da.Fill(ds)
cn.Close
cn = Nothing
Return ds.Tables(0)
End Function

in questo modo me lo gestisco in modo più leggero e con più controllo..

provalo sostituendo la tua stringa di connessione e la tua query sql
Vincenzo
Programmatore sbilenco

Andrew78 Profilo | Newbie

Ok! sto rifacendo praticamente tutto da zero....ho inserito il codice che mi hai girato per creare la classe GetDati()
ma, come riportato nello screenshot non riesce a definire OledbConnection, OleDbCommand, DbDataAdapter e OlDbCommanduilder...strano perchè
System.Data è presente nei References della WebApplication....


1264x695 174Kb

ysdemarc Profilo | Expert

devi inserire anche System.Data.OleDb

oppure le scrivi così System.Data.OleDb.OledbConnection

Vincenzo
Programmatore sbilenco

Andrew78 Profilo | Newbie

Ok...ho corretto...ora provo a fare come dici....

Ti ringrazierò infinitamente per l'aiuto che mi stai dando!!!...

ysdemarc Profilo | Expert

non devi chiamare quel metodo..ho sbagliato io chiamando la routine in quel modo

scrivi questo

private sub DataBind()

DataGrid1.DataSource = dt
DataGrid1.DataBind()

End Sub

e al posto di quel dataBinding chiami DataBind() cioè la routine sopra.. oppure la sostituisci con le 2 righe di codice sopra
Vincenzo
Programmatore sbilenco

Andrew78 Profilo | Newbie

INCREDIBILE....MA VERO!!!....funziona!!!!.....

ecco lo screenshot!.....

1057x601 63Kb


Ora per riuscire a inserire e cancellare i record nella griglia?...pensavo di fare 2 paginette apposta,come consigliato da te, ma in che modo?.....ah...se noti ho messo un bottoncino exit che dovrebbe uscire e chiudere l'applicazione...vorrei sapere se esiste un comando che fa ciò...senza passare dal browser....

ysdemarc Profilo | Expert

nel modo come hai inserito il pulsante Edit..puoi inserire gli altri come Elimina..

poi dall'evento apposito, in questo caso DeleteCommand
in c# è
private void DataGrid1_DeleteCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{

}

gestisci l'eliminazione.. o meglio.. dalla riga in cui l'utente ha cliccato elimina usando l'oggetto DataGridCommandEventArgs
e.Item.Cells ti restituisce la riga in questione.. ti prendi la chiave della cella e la vai a cancellare dalla base dati..e poi riaccedi al db per riempire il datagrid..

la stessa cosa per gli altri..

cmq.. mi spaventa il tuo "ma come?"

per inserire i dati creati un webform con un modulo dove prevedi i campi coi pulsanti adatti ecc.. ecc... ma queste sono cose che neanche bisogna chiedere
Vincenzo
Programmatore sbilenco

Andrew78 Profilo | Newbie

...lo so purtroppo...solo che praticamente è la prima volta che mi cimento con visual studio...infatti ti chiedo scusa se ti ho tirato pazzo fin quì...lo so che per te sono cavolate ma per me è l'opposto...non è che sai consigliarmi qualche guida o qualche piccolo esempio pratico sul "come fare"....
Nel frattempo ti ringrazio!...

ysdemarc Profilo | Expert

contattami in privato dal profilo e mi passi la tua email..se ti interessa ho un manuale niente male
Vincenzo
Programmatore sbilenco

Andrew78 Profilo | Newbie

Ok...ti ho contattato sul profilo!...
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