Ottenere l'indice di riga da DataTable e Dataview

di Fabio Civerchia, in ASP.NET,

L'indice di riga è la posizione di un determinato Record in un resulset e chi proviene da ADO , ha notato sicuramente che la differenza tra ADO.NET e quest'ultimo è sicuramente notevole.

Uno dei problemi che potreste incontrare durante le vostre prime prove è la mancanza di un metodo per recuperare l'indice di riga data una particolare chiave di ricerca.

Un metodo Find lo ritroviamo nell'oggetto DataTable e cj restituisce una matrice di DataRows , ma non la posizione della prima occorrenza utile a soddisfare la ricerca.

Quando ci si scontra con alcuni progetti che richiedono ancora tale funzione bisogna trovare metodi alternativ. In questo articolo vedremo come ottenere l'indice di riga da due oggetti fondamentali in ADO.NET che sono il DataTable e il DataView.

Cercare l'occorrenza

Ecco allora un esempio: immaginate di dover mostrare sempre tutti i record di una tabella e paginarli in una DataGrid , poi di dover effettuare una ricerca su questa tabella e mostrare non solo i record paginati, ma posizionarsi anche sulla prima occorrenza della nostra ricerca.

Nell'esempio che segue, visualizziamo tutti i CompanyName della tabella Customers del DataBase Northwind.

Immagine

A questo punto inseriamo nella casella di testo la stringa Paris ed osserviamo il risultato.

Immagine

Come si può notare nell'immagine non si è estratto solo i record che hanno soddisfatto i nostri criteri, ma la ricerca si è indirizzata nella pagina dove ha trovato la prima occorrenza utile a soddisfare la ricerca stessa.

Ecco il codice necessario per arrivare a questa funzionalità:

Private Sub Binding()
  Dim StrCon As String = "Initial Catalog=Northwind;Data Source=localhost;Integrated Security=SSPI;"
  Dim SqlStr As String = "SELECT CompanyName FROM Customers"
  Dim Cnn As New SqlConnection(StrCon)
  Dim Ds As New DataTable
  Dim Da As New SqlDataAdapter(SqlStr, Cnn)
  Dim dt As New DataTable
 'Try

  Da.Fill(dt)

  If TextBox1.Text <> "" Then
   If RadioButton1.Checked Then'Ricerca con DataTable
     Nriga = Find(dt)
   Else'Ricerca con la Vista
     Nriga = Find(dt.DefaultView)
   End If

   If Nriga > 0 Then
     Dim Position As Int32
     If Nriga Mod GridResult.PageSize = 0 Then
      Position = (Nriga \ GridResult.PageSize) - 1
     Else
      Position = (Nriga \ GridResult.PageSize)
     End If
     GridResult.CurrentPageIndex = Position
   End If
  End If

  GridResult.DataSource = dt
  GridResult.DataBind()
End Sub

La funzione Binding estrae tutti i dati, mentresolo la funzione Find ci permette di ottenere l'indice di riga per la nostra ricerca.

Tale funzione non fa altro che applicare il metodo Find , nel caso di un DataTable, o RowFilter , nel caso di un DataView, per effettuare la ricerca, come fareste normalmente.

Per ottenere l'indice dobbiamo far uso della classe Reflection per andare a vedere il campo rowID che valore ha assunto.

RowID è infatti un campo non pubblico di una DataRow e contiene di fatto l'indice di riga, ovvero la posizione che ha all'interno di un oggetto DataTable o DataView. Vediamo come fare:

Private Function Find(ByVal Dt As DataTable) As Int32<br />
  Dim Righe() As DataRow = Dt.Select(&quot;CompanyName Like'&quot; &amp; TextBox1.Text.Replace(&quot;'&quot;, &quot;''&quot;) &amp; &quot;%'&quot;)<br />
  If Righe.Length &gt; 0 Then<br />
    Dim rowFieldsInfo As FieldInfo = GetType(DataRow).GetField(&quot;rowID&quot;, BindingFlags.NonPublic    Or   BindingFlags.Instance)<br />
    Dim rowId As Int32 = Convert.ToInt32(rowFieldsInfo.GetValue(Righe(0)))<br />
    Return rowId<br />
  End If<br />
End Function<br />
<br />
Private Function Find(ByVal DV As DataView) As Int32<br />
  DV.RowFilter = &quot;CompanyName Like'&quot; &amp; TextBox1.Text.Replace(&quot;'&quot;, &quot;''&quot;) &amp; &quot;%'&quot;<br />
  If DV.Count &gt; 0 Then<br />
<br />
    Dim Riga As DataRowView = DV.Item(0) 'recupero la prima riga<br />
   ' Converto DataRowView in una DataRow<br />
    Dim rowFieldsInfo As FieldInfo = GetType(DataRowView).GetField(&quot;row&quot;, BindingFlags.NonPublic Or BindingFlags.Instance)<br />
    Dim NuovaRiga As DataRow = CType(rowFieldsInfo.GetValue(Riga), DataRow)<br />
<br />
    Dim rowFieldsInfo2 As FieldInfo = GetType(DataRow).GetField(&quot;rowID&quot;, BindingFlags.NonPublic Or BindingFlags.Instance)<br />
    Dim rowId As Int32 = Convert.ToInt32(rowFieldsInfo2.GetValue(NuovaRiga))<br />
    DV.RowFilter = &quot;&quot;<br />
    Return rowId<br />
  End If<br />
  DV.RowFilter = &quot;&quot;<br />
End Function

L'overload di tale funzione è data dal fatto che il percorso per ottenere l'indice di riga in un oggetto DataView è un pò più articolato, perchè bisogna di fatto ottenere un oggetto DataRow da un oggetto DataRowView, il quale non espone nessun membro pubblico per tale oggetto.

Conclusioni

Anche se molto semplice, l'articolo di oggi, sfruttando due caratteristiche del .NET Framework, come la reflection e l'uso di collection per contene i dati, ci ha mostrato un tipico utilizzo di vecchie caratteristiche, disponibili con ADO, all'interno delle nuove funzionalità offerte da ADO.NET.

Approfondimenti

Contenuti dell'articolo

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti