Sie sind auf Seite 1von 39

PROGRAMACIÓN

.NET - II

SEMANA 6
Acceso desconectado a datos

Todos los derechos de autor son de la exclusiva propiedad de IACC o de los otorgantes de sus licencias. No está
permitido copiar, reproducir, reeditar, descargar, publicar, emitir, difundir, poner a disposición del público ni 1
ESTE DOCUMENTO CONTIENE LA SEMANA 6
utilizar los contenidos para fines comerciales de ninguna clase.

2
ESTE DOCUMENTO CONTIENE LA SEMANA 6

ÍNDICE

ACCESO DESCONECTADO A DATOS .................................................................................................... 4
OBJETIVO ESPECÍFICO .............................................................................................................................. 4
INTRODUCCIÓN ..................................................................................................................................... 4
1. ACCESO DESCONECTADO ................................................................................................................ 5
1.1. OBJETOS COMUNES DE ADO.NET PARA ACCESO DESCONECTADO ................................... 6
1.1.1. LA CLASE DATASET ...................................................................................................... 6
1.1.2. LA CLASE DATAADAPTER ............................................................................................ 8
1.1.3. EJEMPLO ..................................................................................................................... 8
1.2. NAVEGACIÓN DE REGISTROS EN MODO DESCONECTADO .............................................. 11
1.3. DATABINDING ................................................................................................................... 19
1.4. EDICIÓN DE REGISTROS EN MODO DESCONECTADO ....................................................... 22
1.4.1. AGREGAR UN REGISTRO ........................................................................................... 25
1.4.2. MODIFICAR UN REGISTRO ........................................................................................ 30
1.4.3. ELIMINAR UN REGISTRO ........................................................................................... 34
COMENTARIO FINAL ......................................................................................................................... 37
REFERENCIAS ....................................................................................................................................... 38

3
ESTE DOCUMENTO CONTIENE LA SEMANA 6

ACCESO DESCONECTADO A DATOS


OBJETIVO ESPECÍFICO
• Aplicar el uso de propiedades, clases y métodos en el acceso desconectado a bases de
datos.

INTRODUCCIÓN
En más de alguna oportunidad nos han ofrecido algún producto, ya sea una tarjeta de crédito, un
seguro, y nos han dicho que al día siguiente se habilitarían los servicios. Probablemente, esa
persona estuvo ingresando nuestros datos con un Tablet, un iPad o un notebook, incluso sin tener
acceso a internet. ¿Cómo es posible hacer esto? La respuesta es: usando el acceso desconectado a
datos.

Anteriormente, se ha estudiado el acceso conectado a datos. El objetivo de esta clase es analizar el


acceso desconectado, y todas las ventajas que tiene por sobre el otro tipo de acceso. Se conocerán
las principales clases que se utilizan y con algunos ejemplos usando MySQL quedará muy claro la
forma en que se pueden utilizar.

4
ESTE DOCUMENTO CONTIENE LA SEMANA 6

1. ACCESO DESCONECTADO
Como es sabido, ADO.NET permite 2 tipos de acceso a un origen de datos: conectado y
desconectado. El modo conectado es el que permite que se efectúen transacciones directamente,
y en tiempo real hacia la base de datos. Esta semana se estudiará el modo desconectado, que
consiste en mantener la base de datos, o parte de ella, en una memoria “local”, lo que permite:

- un acceso mucho más eficiente y rápido.


- una mejora en el tiempo de ejecución de las transacciones, pues no se utilizan recursos del
servidor.
- el aumento en la cantidad de usuarios concurrentes, y por ende, la escalabilidad.
- que los datos son totalmente transportables, dado que generalmente se utiliza XML y es
posible enviarlos y recibirlos mediante un protocolo http, para uso en páginas ASP.NET.

Una vez realizadas todas las operaciones necesarias en los datos del DataSet, se realiza un
traspaso o actualización desde el DataSet hacia la base de datos, y de esa forma se sigue
manteniendo la consistencia en los datos.

El esquema de la arquitectura ADO.NET se puede ver de la siguiente manera:


Figura 1. Arquitectura ADO.NET
Fuente: https://msdn.microsoft.com/es-cl/library/aa719511(v=vs.71).aspx

El lado derecho muestra el modo desconectado. Los datos residen en el DataSet y sobre este se
efectúan las consultas y transacciones. No obstante, previamente se debe haber cargado esa
DataSet con los datos.

5
ESTE DOCUMENTO CONTIENE LA SEMANA 6

Sin embargo, se deben tener ciertas consideraciones importantes:

- La actualización de los mismos registros solicitada por varios usuarios. En este caso, es
necesario gestionar los conflictos y establecer políticas de actualización, como por
ejemplo:
o Que prevalezca la primera actualización.
o Que prevalezca la actualización más reciente.

- Si varios usuarios usan las mismas tablas, no podrán tener acceso a las últimas
actualizaciones de indicadores importante, como por ejemplo el valor del dólar, el valor de
la UF, etc.

1.1. OBJETOS COMUNES DE ADO.NET PARA ACCESO DESCONECTADO


Las clases más importantes del acceso desconectado son DataSet y DataAdapter. Y a su vez,
dentro de la DataSet se tienen las clases DataTable, y dentro de esta DataRow y DataColumn.

1.1.1. LA CLASE DATASET

Sin duda, la clase DataSet es la clase más importante en la arquitectura ADO.NET, sobre todo a
nivel de trabajar sin conexión a la base de datos. El DataSet se puede ver como una representación
de una memoria que “encapsula” la base de datos a nivel lógico, es decir, incluye tablas,
relaciones, vistas, integridad referencial, etc., y que se carga al momento de la primera conexión y
proporciona un modelo de programación relacional, sin importar el origen de datos.

Gráficamente, haciendo una especie de “zoom” en el lado derecho de la Figura 1, un DataSet se


puede ver de la siguiente manera:

6
ESTE DOCUMENTO CONTIENE LA SEMANA 6

Figura 2. Detalle de un DataSet


Fuente: https://msdn.microsoft.com/es-es/library/zb0sdh0b(v=vs.110).aspx

Lo importante del esquema mostrado es que el DataSet se compone de una DataTableCollection,
que contiene una colección de cero o más tablas, donde cada una de ellas es un objeto DataTable,
y residen en memoria, y entre ellas se relacionan mediante una DataRelationCollection. A su vez,
la DataTable se compone de una DataColumnCollection, que corresponde a una colección de
columnas, donde cada una es un objeto DataColumn, y a la vez la DataTable se compone de una
DataRowCollection, que corresponde a una colección de filas, donde cada una es un objeto
DataRow. Cabe destacar que la DataRow es capaz de conservar el estado actual de la fila y la
versión original; de esta forma se pueden identificar los cambios que pudo haber experimentado
la fila.

Los constructores, métodos y propiedades más usados de los DataSet se


pueden conocer y revisar en el Recurso Adicional 1: “Constructores,
métodos y propiedades de esta semana”, págs. 1-3.

Se invita al alumno a conocer más constructores, métodos y propiedades de los DataSet en la


referencia bibliográfica indicada como Microsoft (2016a).

7
ESTE DOCUMENTO CONTIENE LA SEMANA 6

Los constructores, métodos y propiedades más usados de los DataTable se


pueden conocer y revisar en el Recurso Adicional 1: “Constructores,
métodos y propiedades de esta semana”, págs. 4-5.

Se invita al alumno a conocer más constructores, métodos y propiedades de los DataTables en la


referencia bibliográfica indicada como Microsoft (2016b).

1.1.2. LA CLASE DATAADAPTER

Corresponde a una clase que dispone de un conjunto de comandos SQL utilizados para poblar el
DataSet, y a su vez puede establecer una conexión a la base de datos para cuando sea necesario
actualizarla desde el DataSet. Es decir, el DataAdapter es “un canal” que une el DataSet con la
base de datos para efectos de recuperación y actualización.

Además, dispone de una propiedad muy importante llamada TableMapping que relaciona las
tablas del DataSet con su tabla homóloga de la base de datos.

Al igual que el DataReader, el DataAdapter también depende del proveedor, de tal forma que
existirán las clases SqlDataAdapter, OleDBDataAdapter, MySqlDataAdapter, etc.

Los constructores, métodos y propiedades más usados de los DataAdapter


se pueden conocer y revisar en el Recurso Adicional 1: “Constructores,
métodos y propiedades de esta semana”, págs. 6-7.

Se invita al alumno a conocer más constructores, métodos y propiedades de los DataAdapter en la


en la referencia bibliográfica indicada como Microsoft (2016c).


1.1.3. EJEMPLO

Para tener, por ahora, una idea preliminar de cómo interactúa un DataSet con un DataAdapter,
obsérvese el siguiente ejemplo en el que se poblará un ComboBox a partir de una tabla del
DataSet. Considere este pequeño modelo de datos creado en la base de datos sakila.

8
ESTE DOCUMENTO CONTIENE LA SEMANA 6

Se crea un nuevo proyecto, con un nuevo formulario, y en primera instancia consta solo de un
ComboBox.


La idea es:
- Crear la conexión a la base de datos
- Crear un DataAdapter, con la sentencia sql que liste los nombres de las bandas.
- Crear una instancia de un DataSet.
- Poblar la tabla “bandas” del DataSet.
- Desconectarse de la base de datos.
- Asigna la tabla a una DataTable.
- Leer los DataRows (filas) de la Datable y llenar el ComboBox.

9
ESTE DOCUMENTO CONTIENE LA SEMANA 6

El código queda de la siguiente manera:




Imports MySql.Data.MySqlClient
Public Class frBandas
Public myStrConnection As String = "DataSource=localhost; " & _
"Database=sakila; " & _
"Uid=root; " & _
"Pwd=123momia;"
Public myConnection As MySqlConnection = New MySqlConnection(myStrConnection)
Public myDataSet As New DataSet()

Private Sub CargaComboBandas()
Dim sqlSentence As String
sqlSentence = "SELECT bnd_nombre FROM banda ORDER BY bnd_nombre"

Try
Dim myAdapter As MySqlDataAdapter = New MySqlDataAdapter(sqlSentence,
myConnection)
myConnection.Open()
myAdapter.Fill(myDataSet, "Bandas")

Dim miTabla As DataTable


miTabla = myDataSet.Tables("Bandas")

Dim miFila As DataRow
For Each miFila In miTabla.Rows
cbBandas.Items.Add(miFila.Item("bnd_nombre"))
Next
Catch ex As Exception
MessageBox.Show("Error: " & ex.Message)
Finally
myConnection.Close()
End Try
End Sub

Private Sub frBandas_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
CargaComboBandas()
End Sub
End Class


Y la ejecución muestra lo siguiente:

10
ESTE DOCUMENTO CONTIENE LA SEMANA 6

1.2. NAVEGACIÓN DE REGISTROS EN MODO DESCONECTADO


La navegación consiste en recorrer los registros de una tabla, teniendo la posibilidad de avanzar al
siguiente, retroceder al anterior, ir al primero, o bien, avanzar hasta el último. Para desarrollar
esta funcionalidad, se utilizará la tabla employees de la BD Northwind, incluida en MySQL.

La base de datos northwind se puede descargar desde


http://fferegrino.blogspot.cl/2011/10/northwind-en-mysql.html

En caso de no tener esta base de datos en el servidor de MySQL, se puede cargar mediante el
siguiente comando. Cabe mencionar que es necesario haber descargado el archivo
NorthwindMySQL.sql desde el link referenciado anteriormente, y dejarlo en algún directorio, que
en este caso es C:\northwind.

mysql -t -uroot -p < "C:\northwind\NorthwindMySQL.sql"

La tabla tiene la siguiente estructura:

11
ESTE DOCUMENTO CONTIENE LA SEMANA 6

Para recorrerla, se creará un nuevo proyecto, con un nuevo formulario, en el que se agregarán
varios labels, textboxes, botones, groupBox y un panel, para navegar, que abarcarán casi la
totalidad de los campos de la tabla. El diseño se ve de la siguiente manera:

Inicialmente se definen algunas variables globales que serán usadas en varios métodos de la
aplicación.

Public Class frNavegacion
Public myStrConnection As String = "DataSource=localhost; " & _
"Database=northwind; " & _
"Uid=root; " & _
"Pwd=123momia;"
Public myConnection As MySqlConnection = New MySqlConnection(myStrConnection)
Public myDataSet As New DataSet()
Private numRegistro As Integer
Private miTabla As DataTable


La variable:
- myDataSet: corresponde a una instancia de la clase DataSet, que contendrá la o las tablas
de la base de datos sobre las que se desea trabajar.
- numRegistro: será la que indique la fila de la tabla en la que se está posicionado mientras
se navega.
- miTabla: corresponde a una instancia de la clase DataTable que contendrá los registros de
una tabla en particular.

12
ESTE DOCUMENTO CONTIENE LA SEMANA 6

Se debe crear un método que realice la carga de la tabla desde la base de datos:



Private Sub CargaDatosEmpleados()
Dim sqlSentence As String

sqlSentence = "SELECT * FROM employees ORDER BY EmployeeId"

Try
Dim myAdapter As MySqlDataAdapter = New MySqlDataAdapter(sqlSentence,
myConnection)
myConnection.Open()
myAdapter.Fill(myDataSet, "Empleados")
miTabla = myDataSet.Tables("Empleados")
myConnection.Close()
Catch ex As Exception
MessageBox.Show("Error: " & ex.Message)
End Try
End Sub


Nótese que:
- El resultado de la sentencia sql se carga en una tabla de la DataSet llamada Empleados,
mediante el método Fill del DataAdapter.
- A la variable miTabla se le asigna la estructura y contenido de la tabla Empleados
mediante la propiedad Tables del DataSet.

Dado que en la navegación la forma de llenar los controles de la pantalla es “rutinaria”, conviene
crear un método que realice esa función, al que se le indique el número de la fila que se requiere
visualizar. En este caso, se crea el método muestraDatosEmpleado.



Private Sub muestraDatosEmpleado(ByVal numFila As Integer)

Dim miFila As DataRow = miTabla.Rows(numFila)
txEmployeeId.Text = miFila.Item("EmployeeID")
txFirstName.Text = miFila.Item("FirstName")
txLastName.Text = miFila.Item("LastName")
txTitle.Text = miFila.Item("Title")
txTitleOfCourtesy.Text = miFila.Item("TitleOfCourtesy")
txBirthDate.Text = miFila.Item("BirthDate").ToString()
txHireDate.Text = miFila.Item("HireDate").ToString()
txAddress.Text = miFila.Item("Address")
txRegion.Text = miFila.Item("Region")
txCity.Text = miFila.Item("City")
txCountry.Text = miFila.Item("Country")
txPostalCode.Text = miFila.Item("PostalCode")
txHomePhone.Text = miFila.Item("HomePhone")
txExtension.Text = miFila.Item("Extension")
txNotes.Text = miFila.Item("Notes")

End Sub

13
ESTE DOCUMENTO CONTIENE LA SEMANA 6

Entonces, el evento Load queda de la siguiente manera:




Private Sub frNavegacion_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
End CargaDatosEmpleados()
Sub


La navegación viene dada por la funcionalidad de que se le da a los botones Primero, Anterior,
Siguiente y Último.

Para el botón Primero, se tiene:


Private Sub btPrimero_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btPrimero.Click
numRegistro = 0
EndmuestraDatosEmpleado(numRegistro)
Sub


Nótese que se define que el registro a leer es el número cero. Recordar que los registros de una
tabla comienzan en el cero.

Para el botón Último, se tiene:

Private Sub btUltimo_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btUltimo.Click
numRegistro = miTabla.Rows.Count - 1
muestraDatosEmpleado(numRegistro)
End Sub

Nótese que se define que el registro a leer corresponde al resultado obtenido de la resta entre el
total de registros, menos uno. Por ejemplo, si la tabla tiene diez registros, el registro a leer es el
noveno.
Para el botón Anterior, se tiene:



Private Sub btAnterior_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btAnterior.Click
numRegistro = numRegistro - 1
If numRegistro < 0 Then
MessageBox.Show("Error de Navegación" & vbCrLf & "No existe registro
anterior al primero")
Exit Sub
End If
muestraDatosEmpleado(numRegistro)
End Sub

14
ESTE DOCUMENTO CONTIENE LA SEMANA 6

Nótese que, para ir al registro anterior, al registro actual se le resta uno, sin embargo, es necesario
validar que, si se está en el primer registro, no hay manera de seguir retrocediendo.

Para el botón Siguiente, se tiene:


Private Sub btSiguiente_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btSiguiente.Click
numRegistro = numRegistro + 1
If (numRegistro > miTabla.Rows.Count - 1) Then
MessageBox.Show("Error de Navegación" & vbCrLf & "No existe registro
posterior al último")
Exit Sub
End If
muestraDatosEmpleado(numRegistro)
End Sub


Nótese que, para ir al registro siguiente, al registro actual se le suma uno, sin embargo, es
necesario validar que, si se está en el último registro, no hay manera de seguir avanzando.

La ejecución entrega lo siguiente:

15
ESTE DOCUMENTO CONTIENE LA SEMANA 6

Al dar clic en el botón Primero, se muestra el primer registro.



Se da clic en Siguiente:

16
ESTE DOCUMENTO CONTIENE LA SEMANA 6

Se da clic en Último:




Se da clic en Anterior:

17
ESTE DOCUMENTO CONTIENE LA SEMANA 6

Ahora bien, el formato de las fechas de nacimiento y contrato no es la mejor para mostrar en una
pantalla. Se introducirán dos controles MaskedTextBox, que son TextBox a los que se les pueda
dar un formato para mostrar la información. Dentro del ToolBox, están en la agrupación Common
Controls.

Entonces se quitan los TextBox de las fechas, y se agregan los MaskedTextBox. Y en la propiedad
Mask, se da clic en los puntos suspensivos y se escoge la máscara correspondiente a Fecha.

18
ESTE DOCUMENTO CONTIENE LA SEMANA 6

En tiempo de diseño, se ven de la siguiente manera:



Y se cambia el código del método para asignar los valores a los nuevos controles.


Donde dice:
txBirthDate.Text = miFila.Item("BirthDate").ToString()
txHireDate.Text = miFila.Item("HireDate").ToString()

Se cambia por:
mtxBirthDate.Text = miFila.Item("BirthDate").ToString()
mtxHireDate.Text = miFila.Item("HireDate").ToString()



Y la ejecución entrega:




1.3. DATABINDING
Es una propiedad muy importante que permite sincronizar el texto de un control, con un dato de
una columna de una tabla, en particular, de una DataTable, lo que permite optimizar el código. A

19
ESTE DOCUMENTO CONTIENE LA SEMANA 6

continuación, se desarrollará el mismo ejemplo anterior, pero con el uso de DataBindings, para
notar la diferencia.

La sintaxis es:
control.DataBindings.Add("propiedad_control", dataTable, "nombre_columna")
Ejemplo:
Textbox.DataBindings.Add("Text", dtClientes, "primer_nombre")

Esto significa que la propiedad Text del control TextBox se sincroniza con el valor de la columna
primer_nombre de la DataTable dtClientes.

Por lo tanto, el código del método CargaDatosEmpleados() queda de la siguiente manera:


Private Sub CargaDatosEmpleados()
Dim sqlSentence As String
sqlSentence = "SELECT * FROM employees ORDER BY EmployeeId"

Try
Dim myAdapter As MySqlDataAdapter = New MySqlDataAdapter(sqlSentence,
myConnection)
myConnection.Open()
myAdapter.Fill(myDataSet, "Empleados")
miTabla = myDataSet.Tables("Empleados")

txEmployeeId.DataBindings.Add("Text", miTabla, "EmployeeID")
txFirstName.DataBindings.Add("Text", miTabla, "FirstName")
txLastName.DataBindings.Add("Text", miTabla, "LastName")
txTitle.DataBindings.Add("Text", miTabla, "Title")
txTitleOfCourtesy.DataBindings.Add("Text", miTabla, "TitleOfCourtesy")
mtxBirthDate.DataBindings.Add("Text", miTabla, "BirthDate").ToString()
mtxHireDate.DataBindings.Add("Text", miTabla, "HireDate").ToString()
txAddress.DataBindings.Add("Text", miTabla, "Address")
txRegion.DataBindings.Add("Text", miTabla, "Region")
txCity.DataBindings.Add("Text", miTabla, "City")
txCountry.DataBindings.Add("Text", miTabla, "Country")
txPostalCode.DataBindings.Add("Text", miTabla, "PostalCode")
txHomePhone.DataBindings.Add("Text", miTabla, "HomePhone")
txExtension.DataBindings.Add("Text", miTabla, "Extension")

txNotes.DataBindings.Add("Text", miTabla, "Notes")
myConnection.Close()
Catch ex As Exception
MessageBox.Show("Error: " & ex.Message)
End Try
End Sub

Esto permitirá que al iniciar la aplicación, inmediatamente se cargará el primer registro de la
DataTable denominada miTabla.

20
ESTE DOCUMENTO CONTIENE LA SEMANA 6

Ahora, es necesario controlar la navegación de una manera más óptima; esto se logra con el uso
de la clase BindingContext. Esta clase administra la colección de objetos BindingManagerBase
para cualquier objeto que se herede de la clase Control.

Para estos típicos casos de navegación, se usa el objeto BindingContext propio del formulario en
el que se encuentran los controles que muestran información de la base de datos, y es la
propiedad Position del BindingManagerBase la que indicará el registro a leer desde la DataTable.

La sintaxis es:
Form.BindingContext(DataTable).Position = ...
Por ejemplo:
Me.BindingContext(dtClientes).Position = 6

Este código indica que se debe acceder al séptimo registro de la DataTable dtClientes, y los
respectivos controles que están enlazados vía DataBinding se debieran actualizar con los datos de
ese registro. Por lo tanto, el código de los botones Primero, Anterior, Siguiente y Último, cambia y
queda de la siguiente manera:


Private Sub btPrimero_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btPrimero.Click
numRegistro = 0
Me.BindingContext(miTabla).Position = numRegistro
End Sub

Private Sub btUltimo_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btUltimo.Click
numRegistro = miTabla.Rows.Count - 1
Me.BindingContext(miTabla).Position = numRegistro
End Sub

Private Sub btAnterior_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btAnterior.Click
numRegistro = numRegistro - 1
If numRegistro < 0 Then
MessageBox.Show("Error de Navegación" & vbCrLf & "No existe registro
anterior al primero")
Exit Sub
End If
Me.BindingContext(miTabla).Position = numRegistro
End Sub
Private Sub btSiguiente_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btSiguiente.Click
numRegistro = numRegistro + 1
If (numRegistro > miTabla.Rows.Count - 1) Then
MessageBox.Show("Error de Navegación" & vbCrLf & "No existe registro
posterior al último")
Exit Sub
End If
Me.BindingContext(miTabla).Position = numRegistro
End Sub

21
ESTE DOCUMENTO CONTIENE LA SEMANA 6

La ejecución es similar a la mostrada en el punto 1.2. Lo importante es que logró optimizar el


código y enlazar directamente los controles con la DataTable del DataSet.

Se invita al alumno a conocer los constructores, métodos y propiedades de las clases
BindingContext y BindingManagerBase, en la referencia bibliográfica indicada como Microsoft
(2016d) y Microsoft (2016e), respectivamente.


1.4. EDICIÓN DE REGISTROS EN MODO DESCONECTADO
La edición se refiere a la posibilidad de agregar, modificar y/o eliminar un registro de la base de
datos, con la salvedad de que primero la transacción se realiza sobre el DataTable
correspondiente.

Para ser consistente, todos los controles editables (TextBoxes y MaskedTextBoxes) se dejarán con
la propiedad Enabled en False. De tal manera que la ejecución muestre lo siguiente:



Nótese que ningún control se puede editar.

22
ESTE DOCUMENTO CONTIENE LA SEMANA 6

En el formulario se agregarán 5 nuevos botones: Agregar, Modificar, Eliminar, Guardar y Grabar


BD, con la salvedad de que Guardar debe quedar deshabilitado, pues se habilita cuando alguna de
las operaciones se ejecuta. El diseño se ve de la siguiente manera:



Antes de explicar cada una de estas funcionalidades, es necesario realizar algunos cambios en el
código visto anteriormente.
A los atributos de la clase principal se agregan:
- El DataAdapter que se utilizó.
- Una instancia de la clase MySqlCommandBuilder.
- La variable operacion de tipo String, que indicará la operación que se está realizando,
pudiendo ser:
o A: Agregar
o M: Modificar
o E: Eliminar

Por lo tanto, los atributos de la clase quedan así:

Public Class frNavegacion
Public myStrConnection As String = "DataSource=localhost; " & _
"Database=northwind; " & _
"Uid=root;Pwd=123momia;"
Public myConnection As MySqlConnection = New MySqlConnection(myStrConnection)
Public myDataSet As New DataSet()
Private numRegistro As Integer
Private miTabla As DataTable
Private myAdapter As New MySqlDataAdapter()
Private myCommandBuilder As New MySqlCommandBuilder(myAdapter)
Private operacion As String = ""

23
ESTE DOCUMENTO CONTIENE LA SEMANA 6

Otro cambio importante es en el método CargaDatosEmpleados, ya que es necesario inicializar las


propiedades SelectCommand, InsertCommand, UpdateCommand y DeleteCommand del
DataAdapter.


Private Sub CargaDatosEmpleados()
Dim sqlSentence As String
sqlSentence = "SELECT * FROM employees ORDER BY EmployeeId"

Try
myAdapter.SelectCommand = New MySqlCommand(sqlSentence, myConnection)
myAdapter.InsertCommand = myCommandBuilder.GetInsertCommand()
myAdapter.UpdateCommand = myCommandBuilder.GetUpdateCommand()
myAdapter.DeleteCommand = myCommandBuilder.GetDeleteCommand()
myConnection.Open()
myAdapter.Fill(myDataSet, "Empleados")

. . . Lo demás queda igual.



Además, se creará el método ActivaDesactiva que permite dejar habilitados o deshabilitados los
controles para edición de acuerdo al valor del parámetro de entrada flag, que puede ser True o
False.

Private Sub ActivaDesactiva(ByVal flag As Boolean)
txFirstName.Enabled = flag
txLastName.Enabled = flag
txTitle.Enabled = flag
txTitleOfCourtesy.Enabled = flag
mtxBirthDate.Enabled = flag
mtxHireDate.Enabled = flag
txAddress.Enabled = flag
txRegion.Enabled = flag
txCity.Enabled = flag
txCountry.Enabled = flag
txPostalCode.Enabled = flag
txHomePhone.Enabled = flag
txExtension.Enabled = flag
txNotes.Enabled = flag
End Sub


Y a su vez, el código del botón Guardar queda así:

Private Sub btGuardar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btGuardar.Click
If operacion = "A" Then
AgregarRegistro()
End If
If operacion = "M" Then
ModificarRegistro()
End If
ActivaDesactiva(False)
Me.BindingContext(miTabla).Position = numRegistro
btGuardar.Enabled = False
End Sub

24
ESTE DOCUMENTO CONTIENE LA SEMANA 6

Y nótese que:
- Cuando la operación es Agregar, llama al método AgregarRegistro()
- Cuando la operación es Modificar, llama al método ModificarRegistro()
- Desactiva los controles para edición (el flag va en False).
- En pantalla se muestra el registro ingresado o modificado.
- El botón Guardar queda deshabilitado.

Y el código más importante, que corresponde al botón Guardar BD, se muestra a continuación:

Private Sub btGrabarBD_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btGrabarBD.Click
Try
If myDataSet.HasChanges() Then
myAdapter.Update(myDataSet, "Empleados")
myDataSet.AcceptChanges()
MessageBox.Show("BD Actualizada")
End If
Catch ex As Exception
MessageBox.Show("Se produjo el siguiente error: " & vbCrLf & ex.Message)
End Try
End Sub


Y nótese que:
- Se chequea si existen cambios en el DataSet.
- En caso de existir, actualiza la tabla correspondiente a “Empleados” definida en el DataSet,
que en este caso, corresponde a Employee.
- Acepta los cambios, quedando la BD con los mismos registros que el DataSet.

Los métodos AgregarRegistro y ModificarRegistro se explicarán posteriormente.


1.4.1. AGREGAR UN REGISTRO

Para agregar un registro, es necesario mostrar todos los controles vacíos y habilitados para
edición, excepto el del ID, que no es editable, y además indica el número de fila que ocupará en la
tabla. Este número corresponde a la cantidad de filas que tiene la DataTable.

El código del botón Agregar es el siguiente.





25
ESTE DOCUMENTO CONTIENE LA SEMANA 6



Private Sub btAgregar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btAgregar.Click

operacion = "A"
Me.BindingContext(miTabla).AddNew()
txEmployeeId.Text = miTabla.Rows.Count + 1
ActivaDesactiva(True)
txFirstName.Focus()
btAgregar.Enabled = False
btModificar.Enabled = False
btEliminar.Enabled = False
btGuardar.Enabled = True
End Sub


Nótese que:
- Se llama al método AddNew(), que permite crear un nuevo registro en la DataTable, y
como cada TextBox está enlazado a un campo de esta, automáticamente se muestran
todos estos en blanco.
- El valor de txEmployeeId.Text queda con el número total de filas de la tabla, más uno.
Esto es solamente referencial, ya que, en la tabla de la base de datos, el campo
EmployeeId es autoincremental.
- Se llama al método ActivaDesactiva, con el valor del flag en True, lo que indica que todos
los TextBoxes quedan editables.
- El foco queda en el textBox donde se ingresa el nombre del empleado.
- Los botones Agregar, Modificar y Eliminar quedan deshabilitados.
- El botón Guardar queda habilitado.


Ingresados los datos, se presiona el botón Guardar, que, dado que la variable operacion tiene
valor A, entonces llamará al método AgregarRegistro, cuyo código es:

Private Sub AgregaRegistro()


Try
BindingContext(miTabla).EndCurrentEdit()
MessageBox.Show("Registro ingresado correctamente")
numRegistro = miTabla.Rows.Count - 1
operacion = ""
btAgregar.Enabled = True
btModificar.Enabled = True
btEliminar.Enabled = True
Catch ex As Exception
MessageBox.Show("Se produjo el siguiente error: " & vbCrLf & ex.Message)
End Try
End Sub


Nótese que:

26
ESTE DOCUMENTO CONTIENE LA SEMANA 6

- Se llama al método EndCurrentEdit() que detiene la edición del nuevo registro de la


DataTable.
- Muestra un mensaje de confirmación de que el registro se agregó. Si hubiera algún error,
se mostraría un mensaje según se indica en el bloque Catch.
- La variable numRegistro queda apuntando al último registro, que además corresponde al
que se acaba de agregar.
- La variable operacion queda con valor vacío.
- Los botones Agregar, Modificar y Eliminar vuelven a quedar habilitados.

Antes de ejecutar la aplicación, se verán los registros de la tabla Employees en la base de datos.



Nótese que el último registro tiene el número de EmployeeID = 9.

Y la ejecución es la siguiente:
Primero, muestra la pantalla con el primer registro, y todos los controles deshabilitados.

27
ESTE DOCUMENTO CONTIENE LA SEMANA 6



Se da clic al botón Agregar, y se muestra el ID referencial, que en este caso indica que se agregaría
el décimo registro a la tabla, y además todos los TextBoxes están habilitados para edición.
También queda deshabilitado el botón Agregar.



Se ingresan los siguientes datos en los TextBox.

28
ESTE DOCUMENTO CONTIENE LA SEMANA 6



Se presiona el botón Guardar, y se muestra el mensaje:



Se presiona el botón Aceptar, y se obtiene:

29
ESTE DOCUMENTO CONTIENE LA SEMANA 6

Hasta acá, el registro solo se ha agregado en la DataTable para permitir la navegación y visualizar
el cambio en modo desconectado. Para grabarlo en la base de datos, se presiona el botón Grabar
BD, y se muestra el siguiente mensaje:



Al revisar la tabla de la base de datos, efectivamente el registro se agregó.



1.4.2. MODIFICAR UN REGISTRO

Para modificar un registro, es necesario mostrar todos los controles habilitados para edición, y con
los valores que tienen actualmente, ya que la idea es cambiar algún dato del registro que se está
viendo en pantalla.





30
ESTE DOCUMENTO CONTIENE LA SEMANA 6

El código del botón Modificar es el siguiente:




Private Sub btModificar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btModificar.Click
operacion = "M"
ActivaDesactiva(True)
txFirstName.Focus()
btAgregar.Enabled = False

btModificar.Enabled = False
btEliminar.Enabled = False
EndbtGuardar.Enabled
Sub
= True


Nótese que es muy similar al código del botón Aceptar, con la salvedad de que se queda
posicionado en el mismo registro.

Modificados el o los datos, se presiona el botón Guardar, que, dado que la variable operacion
tiene valor M, entonces llamará al método ModificarRegistro, cuyo código es:


Private Sub ModificarRegistro()
Try
BindingContext(miTabla).EndCurrentEdit()
MessageBox.Show("Registro modificado correctamente")
operacion = ""
btAgregar.Enabled = True
btModificar.Enabled = True
btEliminar.Enabled = True
Catch ex As Exception
MessageBox.Show("Se produjo el siguiente error: " & vbCrLf & ex.Message)

End Try
End Sub


Y la ejecución es la siguiente. Se avanzará hasta el quinto registro:

31
ESTE DOCUMENTO CONTIENE LA SEMANA 6



Que en la tabla de la base de datos se ve así:



Se presiona el botón Modificar, y se ve que quedan habilitados todos los TextBox para edición, y
además los botones quedan deshabilitados, quedando habilitado el botón Guardar.

32
ESTE DOCUMENTO CONTIENE LA SEMANA 6

Se modificarán los valores del cargo y la región:



Se presiona el botón Guardar y se muestra el mensaje:

Se presiona el botón Aceptar, y la aplicación se queda en el registro que se modificó.

33
ESTE DOCUMENTO CONTIENE LA SEMANA 6

Se presiona el botón Grabar BD, y luego en la base de datos se puede ver reflejado el cambio.




1.4.3. ELIMINAR UN REGISTRO

Para eliminar un registro, es necesario posicionarse sobre en el registro que se desea borrar
mediante los controles de navegación, y luego presionar el botón Eliminar.

El código del botón Modificar es el siguiente.


Private Sub btEliminar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btEliminar.Click
Dim posicion As Integer

Try
posicion = BindingContext(miTabla).Position

myDataSet.Tables("Empleados").Rows(posicion).Delete()
MessageBox.Show("Registro eliminado correctamente")
operacion = ""
btAgregar.Enabled = True
btModificar.Enabled = True
btEliminar.Enabled = True
Catch ex As Exception
MessageBox.Show("Se produjo el siguiente error: " & vbCrLf & ex.Message)
End Try
End Sub


Nótese que:
- Se obtiene la posición (o fila) en la que se está actualmente.
- Se elimina la fila desde la tabla Empleados del DataSet.
- Se muestra un mensaje de que la eliminación fue exitosa.

El resultado es el siguiente. Se eliminará el registro ingresado en el punto 1.4.1. Para ello se avanza
hasta el final presionando varias veces el botón Siguiente, o bien, se presiona el botón Último.

34
ESTE DOCUMENTO CONTIENE LA SEMANA 6



Se presiona el botón Eliminar, y junto con mostrar el mensaje de que el registro se eliminó
correctamente, de inmediato se posiciona en el registro inmediatamente anterior.



Posteriormente, se presiona el botón Grabar BD, y al revisar la base de datos efectivamente no
está el registro que se había ingresado.

35
ESTE DOCUMENTO CONTIENE LA SEMANA 6

36
ESTE DOCUMENTO CONTIENE LA SEMANA 6

COMENTARIO FINAL
Esta semana se estudió lo relacionado al acceso desconectado y los componentes, clases, métodos
y propiedades más importantes que forman parte de este fabuloso mundo que provee .NET, sobre
todo por lo práctico que resulta trabajar de esta forma en el día a día, cuando se trata de venta de
servicios o productos sin la necesidad de estar conectado a internet o a alguna base de datos local.
Al final del día, es cuestión de conectarse a la red y “aceptar los cambios” para actualizar la base
de datos principal. De todos modos, esto tiene ventajas y desventajas que deben ser consideradas
para evitar conflictos de claves y redundancia de información.

Afortunadamente, MySQL como proveedor de datos dispone de las clases necesarias para realizar
este tipo de acceso y da la posibilidad de que el alumno pueda efectuar sus pruebas y sacarle
provecho a este servidor, como se pudo ver en los ejemplos presentados en este documento.

Además, se dio a conocer la forma en que se puede navegar por los registros de una tabla, y en
particular se mostró el uso de DataBindings, que es muy importante para lograr la sincronización
entre las tablas y los controles de la aplicación.

El acceso desconectado es muy útil cuando se desea realizar una presentación del funcionamiento
de una aplicación. Es típico el caso de que no se puede acceder a ninguna base de datos, ni
siquiera local, ya sea por problemas de máquina virtual, espacio en disco o capacidad del equipo.
Mientras que si se tiene en memoria la información, sería muy práctico efectuar una demo
acotada de un producto de software.

Se invita al alumno a que continúe investigando sobre este tipo de acceso y siga conociendo las
bondades que provee, para que vaya pensando en futuras aplicaciones.

37
ESTE DOCUMENTO CONTIENE LA SEMANA 6

REFERENCIAS
Microsoft (2016a). Clase DataSet. Recuperado de: https://msdn.microsoft.com/es-

es/library/system.data.dataset%28v=vs.110%29.aspx

Microsoft (2016b). Clase DataTable. Recuperado de: https://msdn.microsoft.com/es-

es/library/system.data.datatable(v=vs.110).aspx

Microsoft (2016c). DataAdapter Class. Recuperado de: https://msdn.microsoft.com/en-

us/library/system.data.common.dataadapter%28v=vs.110%29.aspx

Microsoft (2016d). Clase BindingContext. Recuperado de: https://msdn.microsoft.com/es-

es/library/system.windows.forms.bindingcontext(v=vs.110).aspx

Microsoft (2016e). Clase BindingManagerBase. Recuperado de: https://msdn.microsoft.com/es-

es/library/system.windows.forms.bindingmanagerbase(v=vs.110).aspx

PARA REFERENCIAR ESTE DOCUMENTO, CONSIDERE:

IACC (2016). Acceso desconectado a datos. Programación .NET - II. Semana 6.

38
ESTE DOCUMENTO CONTIENE LA SEMANA 6

39
ESTE DOCUMENTO CONTIENE LA SEMANA 6

Das könnte Ihnen auch gefallen