Herramientas de usuario

Herramientas del sitio


cursos:informatica:vb:ado_faq

FAQ

Para ilustrar los ejemplos, utilizaremos el siguiente dataset, llamado DStienda que contiene tablas de articulos, clientes y pedidos y un formulario de mantenimiento de pedidos pedidos_mant, que hemos creado arrastrando los elementos desde la pestaña Origenes de Datos de Visual Studio (Ver esquema)

Cómo añadir elementos a un datatable manualmente

En el formulario:

  Dim artic As DSTienda.articulosRow = DS.articulos.NewRow()
  artic.articulo="003"
  artic.descri="Bota de fútbol"
  artic.estado="A"
  DSTienda.articulos.rows.Add(artic)
  'También se puede hacer a través del bindingsource:
  ArticulosBindingSource.Add(artic)

Una alternativa es utilizar el método AddTABLArow que se crea automáticamente con cada datatable de nombre TABLA, y que recibe como parámetros los nombres de los campos del datatable

  DSTienda.articulos.AddarticulosRow("C01","Chandal",1,23)
  DSTienda.estadosCliente.AddestadosClienteRow("A","Activo")
 

Cómo llenar un datatable desde la base de datos

En el formulario:

  ' Carga todos los articulos de la BD en el datatable 
  ArticulosTableadapter.fill(DStienda.articulos)

Si la tabla de la BD tiene muchas filas, no se debe utilizar este sistema, por cuestiones de rendimiento, sino crear consultas SQL que filtren los datos que se quieren obtener, y hacer cargas parciales de información. Por ejemplo, si queremos cargar los articulos de una familia, creamos una consulta personalizada en articulosTableAdapter, que llamaremos “fillbyFamilia”:

  1. Abrimos el dataset
  2. Con el botón derecho en articulosTablesAdapter, “Agregar Consulta”→“…SQL”→“SELECT que devuelve filas”
  3. Completamos la SQL: “select … from articulos where familia=? order by familia” y pulsamos “Siguiente”
  4. Cambiamos el nombre por “fillbyfamilia”, quitamos la marca a “Devolver un Datatable” y le damos a Siguiente
  5. Finalizar
  ' Carga los articulos de la familia escrita en familiatextbox
  ArticulosTableadapter.fillbyfamilia(DStienda.articulos,familiatextbox.text)

Cómo actualizar la base de datos desde un datatable

Cada fila añadida, modificada o anulada en un datatable queda marcada cambiando su propiedad RowState. De esta forma se sabe si hay que hacer un Insert, Update o Delete al actualizar la base de datos. Para aplicar los cambios del datatable a la base de datos:

  ' Carga los articulos de la familia escrita en familiatextbox
  ArticulosTableadapter.update(DStienda.articulos)

Si estamos en un formulario, antes de hacer el Update es necesario validar la fila que se esté editando:

Private Sub ArticulosBindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 
    Me.Validate() ' Valida los datos del formulario
    ArticulosBindingSource.EndEdit() ' actualiza la fila en edición en el datatable
    ArticulosTableadapter.update(DStienda.articulos) ' actualiza los datos en la base de datos y ejecuta AcceptChanges
End sub

Cómo pasar el datatable a modo inserción

Si queremos pasar un datatable a modo inserción (equivalente a pulsar el + en l bindingnavigator), podemos hacerlo mediante AddNew del bindingsource que está conectado a él:

sub button1_click(...
  clientesbingsource.Addnew() ' Equivale a pulsar el botón Añadir en el bindingnavigator 
end sub

Cómo asignar valores por defecto a una fila nueva

Utilizaremos el evento TableNewRow del datatable.

Private Sub clientesDataTable_TableNewRow(ByVal sender As Object, ByVal e As DataTableNewRowEventArgs) ...
    e.row("estado")="A"  ' Los clientes nuevos se crean en estado 'A'
    e.row("fec_alta")=date.now ' Fecha de alta =hoy
End Sub

Cómo aplicar un filtro

Los filtros y ordenación se hacen siempre mediante un bindingsource conectado a la datatable. De esta forma, podemos tener distintas “vistas” de los datos del datatable simultaneamente conectando varios bindingsource al mismo datatable, y todo ello sin alterar el contenido del mismo.

 articulosbindingsource.filter="estado='A'"
 o
 articulosbindingsource.filter="codigo like '%" & textbusqueda.text & "%' and estado='A'"

Para desactivar el filtro, basta con asignarle “”. Importante: El filtro actúa sobre los datos del datatable, pero NO altera el contenido del mismo ni accede a base de datos. Cuando desactivamos el filtro podemos acceder de nuevo a todos los datos del datatable.

Cómo localizar una fila y posicionarse en ella

 with articulosbindingsource
   .position = .find("articulo",textbox1.text)
 end with

Cómo acceder a los datos de la posición actual de un Bindingsource

La propiedad Current.Row del bindingsource me devuelve el DataRow activo, y a partir de ahí accedemos a los campos del mismo. Por ejemplo: si tenemos un Datagrid y queremos que al hacer doble-clic en una fila se abra un formulario para editar el articulo seleccionado, en el evento doble-clic del Datagrid pondremos algo así:

 dim articuloactivo as DStienda.articulosRow
 with articulosbindingsource
   if .current isnot nothing then 
     articuloactivo = .current.row
     EditarArticulo.editar(...articuloactivo.codigo) ' El formulario EditarArticulo tiene un método editar que recibe el código del articulo que se desea editar
   else
     MsgBox("No hay articulo en la selección")
   end if 
 end with

Cómo validar datos

La validación de datos de cada DataRow ha de hacerse siempre que se pueda en el Dataset, y así nos aseguramos de que siempre se hará, independientemente de que tengamos varios formularios para editar el mismo datatables. Utilizaremos el evento ColumnChanging del Datatable (haciendo doble clic en el campo que queremos validar del datatable, se genera el código del evento:

   Private Sub clientesDataTable_ColumnChanging(ByVal sender As System.Object,e as DataColumnChangeEventArgs)...
      If (e.Column.ColumnName = "nif") Then
           If e.ProposedValue.ToString.Length <> 9 Then
               e.Row.SetColumnError("nif", "NIF Incorrecto")
           Else
               e.Row.SetColumnError("nif", "")
           End If
      End If
   End Sub
  • e.Column me devuelve la columna que se está cambiando
  • e.proposedvalue es el valor que se quiere asignar a la columna (el que hay que validar)
  • e.Row me devuelve la datarow activa. Esto me permite asignar valores a otros datos en función del que está cambiando.
  • Para asignar un mensaje de error a una columna, utilizamos e.Row.SetColumnError(columna, mensaje)

Otro ejemplo, con las lineas de un pedido, en el que al cambiar el código del artículo, asignamos el precio de la linea a partir del precio del articulo (suponemos que el datatable articulos ya está relleno con todos los articulos)

        Private Sub pedlineasDataTable_ColumnChanging(ByVal sender As System.Object, ByVal e As DataColumnChangeEventArgs)...
            If (e.Column.ColumnName = Me.articuloColumn.ColumnName) Then
                ' busco el articulo y asigno el precio
                Dim art As articulosRow = CType(Me.DataSet, DSarticulos).articulos.FindByarticulo(e.ProposedValue)
                If art IsNot Nothing Then
                    e.Row("precio") = art.precio
                    e.Row.SetColumnError("articulo", "")
                Else
                    e.Row.SetColumnError("articulo", "Articulo inexistente")
                    e.ProposedValue = ""
                End If
            End If
        End Sub
  • Me.Dataset es el dataset al que pertenece este datatable. Hacemos el casting para acceder más comodamente a articulos, pero podriamos haberlo hecho poniendo Me.dataset.tables(“articulos”)
  • Cada datatable tiene un método llamado FindByXXXXX(valor) para localizar filas en él accediendo por la primera key

Para que los mensajes de error se visualicen en el formulario, pondremos en éste un ErrorProvider conectado al Bindingsource que queramos.

Cómo crear un formulario maestro-detalle

Para hacer un formulario maestro-detalle tiene que haber un relación entro la tabla maestra y la de detalle . En nuestro ejemplo: pedidos→pedlineas. Vamos a hacer un formulario de edición de un pedido, que tiene los campos del datatable pedidos en la parte superior, y un grid de pedlineas en la parte inferior:

  • Creamos la parte de la cabecera (pedidos), arrastrando los campos que queramos
  • Arrastramos pedlineas al formulario para crear el grid, pero cogiendo el que hay dentro de pedidos, no el que aparece a primer nivel. De esta forma, el pedlineasbindingsource no se conecta directamente al datatable pedlineas, sino que lo hace a la relación entre pedidos y pedlineas, y así tendremos que:
    • Cuando en pedidos estemos situados en un pedido determinado, en el grid solamente se mostrarán las lineas de ese pedido
    • Si cambiamos de posición en pedidosbindingsource, el grid se refrescará automáticamente
    • Cuando añadimos una nueva linea a pedlineas, el campo pedido se asigna automáticamente al código de pedido de la cabecera