vb_net_bd_2005_02

17
1 1. Otros. 1.1 Introducción. Una vez visto los objetos de conexión, vamos a ver una serie de objetos que realizan también tareas dentro del acceso a una base de datos. 1.2 BindingSource. Este objeto tiene como misión el realizar el enlace entre dos objetos que no pueden enlazarse directamente por carecer del recurso adecuado. Normalmente el enlace de un origen de datos y uno de visualización se realiza a través de la propiedad DataSource, pero cuando no se dispone de ella, se puede utilizar este objeto para realizar dicho enlace. El objeto más utilizado en la visualización es el datagridview, este objeto dispone de la propiedad DataSource, por lo que su enlace no representa mayor problema. Primero, proporciona una capa de direccionamiento indirecto al enlazar los controles de un formulario a los datos. Esto se lleva a cabo enlazando el componente BindingSource a su origen de datos y enlazando a continuación los controles del formulario al componente BindingSource. Todas la demás interacción con los datos, incluido el desplazamiento, la ordenación, el filtrado y la actualización, se lleva a cabo con llamadas al componente BindingSource. El enlace se lleva a cabo a través de la propiedad DataBindings. Veamos su utilización. Primero los objetos que se van a utilizar. Dim Conexion As New System.Data.OleDb.OleDbConnection Dim Adaptador As New System.Data.OleDb.OleDbDataAdapter Dim Tabla As DataTable = ObjDataSet.Tables("Provincia") Dim EnlaceTabla As New BindingSource Dim Actualizador As New OleDb.OleDbCommandBuilder(Adaptador) Dim CadenaSql As String = "Select * from provincia order by codprov" Y además TextBox, Campo01, que se supone ya en el formulario. Enlace. El enlace se realiza con la propiedad DataBinding del objeto TextBox. Private Sub Enlaces() Campo00.DataBindings.Add("Text", EnlaceTabla, "CodProv") Campo01.DataBindings.Add("Text", EnlaceTabla, "DenomCas") Campo02.DataBindings.Add("Text", EnlaceTabla, "DenomVal") End Sub Los parámetros son ("Text", La propiedad que se va a enlazar, entre comillas, EnlaceTabla, El objeto que se enlaza al TextBox, el que tiene los datos. "CodProv") El nombre del campo en el objeto de origen de los datos, nombre en la tabla. El objeto para poderlo utilizar debe de tener datos, he aquí la carga del mismo.

Upload: avalenzuela

Post on 16-Apr-2015

13 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Vb_Net_BD_2005_02

1

1. Otros.

1.1 Introducción. Una vez visto los objetos de conexión, vamos a ver una serie de objetos que realizan también tareas

dentro del acceso a una base de datos.

1.2 BindingSource. Este objeto tiene como misión el realizar el enlace entre dos objetos que no pueden enlazarse

directamente por carecer del recurso adecuado. Normalmente el enlace de un origen de datos y uno de visualización se realiza a través de la propiedad

DataSource, pero cuando no se dispone de ella, se puede utilizar este objeto para realizar dicho enlace. El objeto más utilizado en la visualización es el datagridview, este objeto dispone de la propiedad

DataSource, por lo que su enlace no representa mayor problema. Primero, proporciona una capa de direccionamiento indirecto al enlazar los controles de un formulario a

los datos. Esto se lleva a cabo enlazando el componente BindingSource a su origen de datos y enlazando a continuación los controles del formulario al componente BindingSource.

Todas la demás interacción con los datos, incluido el desplazamiento, la ordenación, el filtrado y la actualización, se lleva a cabo con llamadas al componente BindingSource.

El enlace se lleva a cabo a través de la propiedad DataBindings. Veamos su utilización. Primero los objetos que se van a utilizar. Dim Conexion As New System.Data.OleDb.OleDbConnection Dim Adaptador As New System.Data.OleDb.OleDbDataAdapter Dim Tabla As DataTable = ObjDataSet.Tables("Provincia") Dim EnlaceTabla As New BindingSource Dim Actualizador As New OleDb.OleDbCommandBuilder(Adaptador) Dim CadenaSql As String = "Select * from provincia order by codprov"

Y además TextBox, Campo01, que se supone ya en el formulario. Enlace. El enlace se realiza con la propiedad DataBinding del objeto TextBox.

Private Sub Enlaces() Campo00.DataBindings.Add("Text", EnlaceTabla, "CodProv") Campo01.DataBindings.Add("Text", EnlaceTabla, "DenomCas") Campo02.DataBindings.Add("Text", EnlaceTabla, "DenomVal") End Sub

Los parámetros son ("Text",

La propiedad que se va a enlazar, entre comillas, EnlaceTabla,

El objeto que se enlaza al TextBox, el que tiene los datos. "CodProv")

El nombre del campo en el objeto de origen de los datos, nombre en la tabla. El objeto para poderlo utilizar debe de tener datos, he aquí la carga del mismo.

Page 2: Vb_Net_BD_2005_02

2

Este ejemplo es con DataSet Private Sub CargaDatos() ObjDataSet.Clear() If Conexion.State = ConnectionState.Closed Then Conexion.Open() Adaptador = New OleDb.OleDbDataAdapter(CadenaSql, Conexion) Adaptador.Fill(ObjDataSet) EnlaceTabla.DataSource = ObjDataSet.Tables(0) ' ("Provincia") Actualizador = New OleDb.OleDbCommandBuilder(Adaptador) Conexion.Close() End Sub

El mismo, pero con un DataTable Private Sub CargaDatos() If Conexion.State = ConnectionState.Closed Then Conexion.Open() Adaptador = New OleDb.OleDbDataAdapter(CadenaSql, Conexion) Adaptador.Fill(Tabla) EnlaceTabla.DataSource = Tabla Actualizador = New OleDb.OleDbCommandBuilder(Adaptador) Conexion.Close() End Sub

Podemos borrar el elemento actual de la tabla, registro actual en el formulario.. EnlaceTabla.RemoveCurrent()

Iniciar los objetos de TextBox en blanco para añadir un nuevo registro. EnlaceTabla.AddNew()

Una vez que se cumplimentan los datos, si quiere grabarse ha de ejecutarse el método

EnlaceTabla.EndEdit. Este objeto además permite realizar tareas de navegación, con los métodos que observamos en el

ejemplo. EnlaceTabla.MoveFirst() EnlaceTabla.MovePrevious() EnlaceTabla.MoveNext() EnlaceTabla.MoveLast()

Y el proceso de actualización es el que sigue. Private Sub Actualizar() Conexion.Open() Try Adaptador.Update(CType(EnlaceTabla.DataSource, DataTable)) MsgBox("Datos actualizados.", MsgBoxStyle.Information, Me.Text) Catch ex As OleDb.OleDbException MsgBox("Datos existentes", MsgBoxStyle.Critical, Me.Text) End Try Conexion.Close() End Sub

Page 3: Vb_Net_BD_2005_02

3

La actualización debe de arrancar, puede, del evento clic de un button, en el que se ejecuta: EnlaceTabla.EndEdit() Actualizar()

La primera línea finaliza la edición del registro que se añadió nuevo, o que se estaba editando. La segunda llama al procedimiento de actualización. Si deseamos cancelar los cambios que se hayan hecho en el registro actual, podemos ejecutar EnlaceTabla.CancelEdit()

Y los cambios en el registro actual se desharán. Todo lo referente al objeto BindingSource podemos encontrarlo en el siguiente Link. http://msdn2.microsoft.com/es-es/library/system.windows.forms.bindingsource(VS.80).aspx

1.3 CommandBuilder. Es un objeto que genera de forma automática el código SQL necesario para proceder a la actualización

de una tabla de la base de datos. No es posible utilizarlo para las tablas que se generen de forma provisional, pues estás tablas suelen

estar compuestas por datos de varias tablas, o para tablas en las que los datos a añadir son una colección de varios registros.

La utilización es relativamente sencilla. En un DataSet el objeto OleDbCommandBuilder puede ser reutilizado y no es necesario tener uno para

cada tabla del DataSet. Va asociado con un objeto DataTable y un DataAdapter, pues el conjunto permite la gestión de los datos. El ejemplo que sigue carga los datos en un DataGridView, y lo deja enlazado a la tabla, de tal forma que

con muy poco más es suficiente para la visualización y la edición de los datos de la tabla. La utilización del CommandBuilder es como sigue: Dim ComandoActualizar As OleDb.OleDbCommandBuilder

A continuación su asignación, no debe moverse del sitio pues sino no dispone de la información

necesaria para generar el código SQL ' Crear un 'commandbuilder' que genere el SQL Update/Insert/Delete ComandoActualizar = New OleDb.OleDbCommandBuilder(Adaptador)

Y el procedimiento completo es el que sigue, para poder tener una visión algo más amplia. Public Sub CargaDataGrid( _ ByVal Conexion As System.Data.OleDb.OleDbConnection, _ ByRef Adaptador As System.Data.OleDb.OleDbDataAdapter, _ ByRef EnlaceTabla As BindingSource, _ ByRef ObjDataGrid As DataGridView, _ ByVal CadenaSql As String) Dim ComandoActualizar As OleDb.OleDbCommandBuilder Dim Tabla As New DataTable Try ' Crear un nuevo adaptador de datos Adaptador = New OleDb.OleDbDataAdapter(CadenaSql, Conexion) ' Crear un 'commandbuilder' que genere el SQL Update/Insert/Delete ComandoActualizar = New OleDb.OleDbCommandBuilder(Adaptador)

Page 4: Vb_Net_BD_2005_02

4

' Llenar la tabla Adaptador.Fill(Tabla) ' Enlazar la tabla ObjDataGrid.DataSource = Tabla Catch ex As OleDb.OleDbException MsgBox(ex.Message, MsgBoxStyle.Information) End Try End Sub

Si en lugar de utilizarlo en un DataTable, se usa en una tabla dentro de un DataSet, no hay cambio

alguno, pues el objeto funciona a nivel de DataTable, no de DataSet, por lo que no hay ningún cambio en su utilización, la definición y el uso es exactamente igual.

Todo lo referente al objeto OleDbCommandBuilder podemos encontrarlo en el siguiente Link. http://msdn2.microsoft.com/es-es/library/system.data.oledb.oledbcommandbuilder(VS.80).aspx

1.4 Command. Nos permite realizar diversos tipos de operaciones con la base de datos. Almacena básicamente el código SQL para interactuar con la base de datos, pero dispone de varias

funcionalidades. En el ejemplo que sigue se usa en la generación de un objeto DataReader para cargar un ListBox con

una consulta incrustada. Su definición es Dim Comando As New System.Data.OleDb.OleDbCommand

Después primero le asignamos el código SQL ' Contenido del comando Comando.CommandText = CadenaSQL

Después le indicamos de que tipo es el código SQL que se le asigna, una cadena de texto, o una

consulta almacenada, en el ejemplo le indicamos que es una cadena de texto. ' Tipo de comando a ejecutar Comando.CommandType = CommandType.Text

Y el siguiente paso es asignarle el origen de datos que se va a utilizar. ' Conexión a utilizar, configurada previamente. Comando.Connection = Conexion

Pasada la fase de definición, se ejecuta el código SQL, asignando el resultado de su ejecución a un

objeto DataReader. ' Ejecución de SQL Reader = Comando.ExecuteReader

En este caso se ha usado el método ExecuteReader, pero disponemos de otra faceta, para cuando no

hay que devolver datos, ExecuteNonQuery, para las instrucciones Update, Delete por ejemplo.

Page 5: Vb_Net_BD_2005_02

5

Veamos el procedimiento completo. Public Sub CargaListaAutores( _ ByRef Lista As ListBox, _ ByVal Conexion As System.Data.OleDb.OleDbConnection) Dim CadenaSQL As String Dim Comando As New System.Data.OleDb.OleDbCommand Dim Reader As System.Data.OleDb.OleDbDataReader Dim Objeto As ItemLista Lista.Items.Clear() CadenaSQL = "Select Codigo, Nombre " & _ "From Autores " & _ "Order By Nombre" Try ' Abrir la base de datos. Conexion.Open() ' Contenido del comando Comando.CommandText = CadenaSQL ' Tipo de comanndo a ejecutar Comando.CommandType = CommandType.Text ' Conexión a utilizar, configurada previamente. Comando.Connection = Conexion ' Ejecución de SQL Reader = Comando.ExecuteReader Try While Reader.Read Objeto = New ItemLista(Trim(Reader.Item("Nombre").ToString), _ Reader.Item("Codigo").ToString) Lista.Items.Add(Objeto) End While Catch ex As OleDb.OleDbException MsgBox(ex.Message, MsgBoxStyle.Information, "Leer reader") End Try Catch Ex As OleDb.OleDbException MsgBox(Ex.Message, MsgBoxStyle.Information, "Crear reader") End Try Conexion.Close() End Sub

Si en lugar de utilizar una cadena SQL, usamos una consulta almacenada en la base de datos, en este

caso en Access, los cambios son estos. ' Nombre de la consulta en la base de datos. Comando.CommandText = "Usp_UpdateProvincia" ' Tipo de comando a ejecutar Comando.CommandType = CommandType.StoredProcedure ' Conexión a utilizar, configurada previamente. Comando.Connection = Conexion

Hay que pensar que el resto es el mismo, solo se ha cambiado la fuente del código SQL, que ahora está

almacenado en la base de datos, y cuando la abra lo capturará.

Page 6: Vb_Net_BD_2005_02

6

La consulta puede ser que incorpore parámetros, como es el caso del ejemplo que se actualizan datos en la tabla, en ese caso hay que añadir el valor de los parámetros.

' Añadir parámetros de la consulta a ejecutar. Comando.Parameters.Add("@Cod", OleDb.OleDbType.Char, 2).Value = Campo01.Text Comando.Parameters.Add("@DeC", OleDb.OleDbType.Char, 11).Value = Campo02.Text Comando.Parameters.Add("@DeV", OleDb.OleDbType.Char, 11).Value = Campo03.Text

El significado de los parámetros es el que sigue. "@Cod",

Es el nombre del parámetro en la consulta almacenada. OleDb.OleDbType.Char, 2)

Es el tipo de dato que se envía, texto de dos caracteres de longitud. .Value = Campo01.Text

Es la forma de darle el valor que se ha de grabar en la base de datos. El código SQL en la consulta que está almacenada en Access es. UPDATE Provincia SET Provincia.CodProv = @Cod, Provincia.DenomCas = @DeC, Provincia.DenomVal = @DeV WHERE (((Provincia.CodProv)=[@Codigo]));

Otro ejemplo del uso del Command es el que sigue. La definición es la misma y la parametrización también. Dim Comando As New System.Data.OleDb.OleDbCommand ' código SQL a utilizar Comando.CommandText = CadenaSQL ' Tipo de comanndo a ejecutar Comando.CommandType = CommandType.Text ' Conexión a utilizar, configurada previamente. Comando.Connection = Conexion

El cambio viene a la hora de la ejecución que como no devuelve datos, se usa otro método. Cuantos = Comando.ExecuteNonQuery

Cuantos es una variable entera que recibe cuantos registros han sido afectados por la ejecución en éste

caso será uno correcto y cero error. Por eso la variable Fallo será true cuando Cuantos valga cero. Este es el procedimiento completo. Private Sub GrabarMovimiento( _ ByVal Conexion As System.Data.OleDb.OleDbConnection, _ ByRef Comando As System.Data.OleDb.OleDbCommand, _ ByVal Fech As String, _ ByVal Edit As String, _ ByVal TipT As String, _ ByVal Titu As String, _ ByVal Cant As String, _ ByRef Fallo As Boolean)

Page 7: Vb_Net_BD_2005_02

7

Dim Cuantos As Integer Dim TiMv As String = "1" ' entradas de almacen Dim Nume As String = Campo01.Text Dim Docu As String = Campo02.Text Dim CadenaSQL As String CadenaSQL = "INSERT INTO Movimientos ( Fecha, Tipo, Codigo, " & _ "TipTitulo, Titulo, TipMov, Cantidad, " & _ "FacAbo, Numero ) " & _ "Values ('" & Fech & "', " & _ "'" & Edit & "', " & _ "'" & Docu & "', " & _ "'" & TipT & "', " & _ "'" & Titu & "', " & _ "'" & TiMv & "', " & _ "'" & Cant & "', " & _ "'0', " & _ "'" & Nume & "') " ' código SQL a utilizar Comando.CommandText = CadenaSQL ' Tipo de comando a ejecutar Comando.CommandType = CommandType.Text ' Conexión a utilizar, configurada previamente. Comando.Connection = Conexion Try Cuantos = Comando.ExecuteNonQuery Fallo = Cuantos = 0 Catch ex As OleDb.OleDbException Fallo = True MsgBox(ex.Message, MsgBoxStyle.Information) End Try End Sub

Todo lo referente al objeto Command podemos encontrarlo en el siguiente Link. http://msdn2.microsoft.com/es-es/library/system.data.oledb.oledbcommand(VS.80).aspx

1.5 DataView. Este objeto permite obtener datos de una tabla a partir de unos criterios definidos. Tiene la característica que permite seleccionar las filas de una tabla que hayan sido modificadas,

borradas o insertadas, siempre que no se haya hecho el volcado o la actualización de los datos en la base de datos.

También se puede indicar porque campo queremos que nos ordene los datos que se van a filtrar. Los pasos son: Asignar la tabla origen de la información. ' Asignación de la tabla ObjDataView.Table = Tabla

Si deseáramos modificar el contenido de la vista, cambiaríamos a true estos valores. ' No se permite edición. ObjDataView.AllowDelete = False ObjDataView.AllowEdit = False ObjDataView.AllowNew = False

Page 8: Vb_Net_BD_2005_02

8

Indicar el contenido del campo a utilizar en el filtro. ' campo a usar en el filtro. ObjDataView.RowFilter = "Tipo = '" & Tipo & "'"

Que filas deseamos visualizar, se puede seleccionar, entre las actuales, solo borradas, insertadas, etc. ' Cuales ObjDataView.RowStateFilter = DataViewRowState.CurrentRows

El campo por el cual queremos la ordenación. ' campo a usar para la ordenación ObjDataView.Sort = "RazonSocial"

Después solo queda recorrer el objeto para capturar el resultado del filtrado. For X = 0 To ObjDataView.Count - 1 Objeto = _ New ItemLista(Trim(ObjDataView(X).Row.Item("RazonSocial").ToString), _ ObjDataView(X).Row.Item("Tipo").ToString, _ ObjDataView(X).Row.Item("Codigo").ToString) Lista.Items.Add(Objeto) Next

El código completo es el que sigue. Public Sub CargaListaClientesDS(ByVal Tabla As DataTable, _ ByRef Lista As ListBox, _ ByVal Tipo As String) Dim X As Integer Dim Objeto As ItemLista Dim ObjDataView As DataView ' Crear el objeto ObjDataView = New DataView(Tabla) ' Definir parámetros With ObjDataView ' Asignación de la tabla .Table = Tabla ' No se permite edición. .AllowDelete = False .AllowEdit = False .AllowNew = False ' campo a usar en el filtro .RowFilter = "Tipo = '" & Tipo & "'" .RowStateFilter = DataViewRowState.CurrentRows ' campo a usar para la ordenación .Sort = "RazonSocial" End With Lista.Items.Clear() For X = 0 To ObjDataView.Count - 1 Objeto = _ New ItemLista(Trim(ObjDataView(X).Row.Item("RazonSocial").ToString), _ ObjDataView(X).Row.Item("Tipo").ToString, _ ObjDataView(X).Row.Item("Codigo").ToString) Lista.Items.Add(Objeto) Next End Sub

Page 9: Vb_Net_BD_2005_02

9

Todo lo referente a este objeto lo podemos encontrar en el siguiente Link. http://msdn2.microsoft.com/es-es/library/system.data.dataview(VS.80).aspx

1.6 DataRelation. Este objeto permite definir las relaciones dentro de un DataSet. Su utilización es como sigue. Private Sub CrearRelacion() ' ' Crear relaciones ' ObjDataSet.Relations.Clear() Dim RelGruAlu As DataRelation = _ ObjDataSet.Relations.Add("GrupoAlumno", _ ObjDataSet.Tables("Grupos").Columns("CodGrupo"), _ ObjDataSet.Tables("Alumnos").Columns("Grupo")) Dim RelAluAsi As DataRelation = _ ObjDataSet.Relations.Add("AlumnosAsignaturas", _ ObjDataSet.Tables("Alumnos").Columns("Exped"), _ ObjDataSet.Tables("AlumnAsig").Columns("Exped")) End Sub

Donde ObjDataSet.Relations.Add("GrupoAlumno", _

es el nombre de la relación dentro del DataSet. ObjDataSet.Tables("Grupos").Columns("CodGrupo"), _

es el campo de la tabla principal, “Grupos”. ObjDataSet.Tables("Alumnos").Columns("Grupo"))

es el campo en la tabla secundaria, “Alumnos”. Se pueden añadir las relaciones necesarias para el control del DataSet. Cuando se añade una relación, se comprueba que está se cumple y si no es así se genera un error. Como se puede observar es para el DataSet, pero en la base de datos tendremos definidas las

relaciones de integridad para la gestión de la misma. Con esas relaciones definidas para una tarea de mantenimiento realizada fuera de un DataSet, es

suficiente, ya que con declararlas como no eliminar en cascada, a la hora de intentar borrar un registro con datos dependientes se genera un error que se puede capturar con el Try Catch del tipo OleDbException.

Vemos un ejemplo en el que se borra un registro en la tabla, sin que haya ningún código en concreto

para la gestión de una relación. Los pasos son :

Generar el código SQL, Asignar los parámetros del objeto OleDbCommand, Ejecutar el código SQL Controlar los errores

Page 10: Vb_Net_BD_2005_02

10

Podemos ver el procedimiento completo. Private Sub Borrar() Dim Comando As New System.Data.OleDb.OleDbCommand Dim Cuantos As Integer Dim CadenaSQl As String CadenaSQl = "Delete From Editoriales " & _ "Where (Editoriales.Codigo = '" & Campo01.Text & "');" Conexion.Open() ' Nombre de la consulta en la base de datos. Comando.CommandText = CadenaSQl ' Tipo de comando a ejecutar Comando.CommandType = CommandType.Text ' Conexión a utilizar, configurada previamente. Comando.Connection = Conexion Try Cuantos = Comando.ExecuteNonQuery Select Case Cuantos Case Is <> 0 MsgBox("Datos borrados", MsgBoxStyle.Information, Me.Text) Case Else ' cuando hay error salta el Catch, y sino MsgBox("Error en borrado", MsgBoxStyle.Information, Me.Text) End Select Catch ex As OleDb.OleDbException MsgBox(ex.Message, MsgBoxStyle.Information, "Error en inserción") End Try Conexion.Close() ' Liberar recursos Comando.Dispose() Comando = Nothing End Sub

Podemos ver la ventana con las propiedades de una relación entre dos tablas, conviene hacer hincapié

en el apartado de no activar la opción de eliminar en cascada, de esa forma podemos evitar algún que otro disgusto.

Con esos pasos es suficiente para la gestión de la relación.

En un DataSet el uso de relaciones mejora la visualización de los datos, con el DataGrid, por ejemplo, ya

que se realiza prácticamente una navegación entre los datos origen y los dependientes. Solo es asignar el DataSet al DataGrid.

Page 11: Vb_Net_BD_2005_02

11

Todo lo referente al DataRelatión lo podemos encontrar en. http://msdn2.microsoft.com/es-es/library/system.data.datarelation(VS.80).aspx

1.7 Restriction. Representa la restricción de una acción impuesta a un conjunto de columnas en una relación entre clave

principal y clave externa cuando se elimina o actualiza un valor o una fila. Paso a paso, con una tabla de campo único. Declarar los objetos que vamos a utilizar. ' Declarar las columnas de las relaciones para las restriciones Dim ColPrincipal As DataColumn Dim ColSecundaria As DataColumn Dim Restriccion As ForeignKeyConstraint

Eliminar anteriores restricciones. ObjDataSet.Tables("Grupos").Constraints.Clear()

Definir las columnas, campos que interviene en la relación de las tablas. ' Establecer los parámetros, grupos alumnos ColPrincipal = ObjDataSet.Tables("Grupos").Columns("CodGrupo") ColSecundaria = ObjDataSet.Tables("Alumnos").Columns("Grupo")

Crear la restricción. Restriccion = New ForeignKeyConstraint("RestGrupoAlumno", _ ColPrincipal, _ ColSecundaria)

Definir las condiciones en borrado, actualización. ' Establecer condiciones de la restricción Restriccion.DeleteRule = Rule.Cascade Restriccion.UpdateRule = Rule.Cascade Restriccion.AcceptRejectRule = AcceptRejectRule.Cascade

Añadir la restricción a las tablas. ' Añadir la restricción ObjDataSet.Tables("Alumnos").Constraints.Add(Restriccion)

Una vez creada la restricción, hay que marcar su utilización. ' Establecer a True la propiedad EnforceConstraints, ' forzar las restricciones. ObjDataSet.EnforceConstraints = True

Page 12: Vb_Net_BD_2005_02

12

El ejemplo completo queda como sigue. Private Sub CrearRestriccion() ' Declarar las columnas de las relaciones para las restriciones Dim ColPrincipal As DataColumn Dim ColSecundaria As DataColumn Dim Restriccion As ForeignKeyConstraint ObjDataSet.Tables("Grupos").Constraints.Clear() ' Establecer los parámetros, grupos alumnos ColPrincipal = ObjDataSet.Tables("Grupos").Columns("CodGrupo") ColSecundaria = ObjDataSet.Tables("Alumnos").Columns("Grupo") Restriccion = New ForeignKeyConstraint("RestGrupoAlumno", _ ColPrincipal, _ ColSecundaria) ' Establecer condiciones de la restricción Restriccion.DeleteRule = Rule.Cascade Restriccion.UpdateRule = Rule.Cascade Restriccion.AcceptRejectRule = AcceptRejectRule.Cascade ' Añadir la restricción ObjDataSet.Tables("Alumnos").Constraints.Add(Restriccion) ' Añadir la restricción ObjDataSet.Tables("AlumnAsig").Constraints.Add(Restriccion) ' Establecer a True la propiedad EnforceConstraints, ' forzar las restricciones. ObjDataSet.EnforceConstraints = True End Sub

El ejemplo anterior es con un solo campo en la clave. El siguiente es con tablas de varios campos en su clave principal. Private Sub CrearRestriccion() ' Declarar las columnas de las relaciones para las restriciones Dim ColPri(3) As DataColumn Dim ColSec(3) As DataColumn Dim Restriccion As ForeignKeyConstraint ' Establecer los parámetros, asignaturas con asignaturas de alumnos ColPri(0) = ObjDataSet.Tables("Areas").Columns("CodNiv") ColPri(1) = ObjDataSet.Tables("Areas").Columns("CodEtapa") ColPri(2) = ObjDataSet.Tables("Areas").Columns("CodFam") ColPri(3) = ObjDataSet.Tables("Areas").Columns("CodArea") ColPri(0) = ObjDataSet.Tables("AlumnAsig").Columns("Nivel") ColPri(1) = ObjDataSet.Tables("AlumnAsig").Columns("Etapa") ColPri(2) = ObjDataSet.Tables("AlumnAsig").Columns("Familia") ColPri(3) = ObjDataSet.Tables("AlumnAsig").Columns("CodAsig") Restriccion = New ForeignKeyConstraint("RestAlumAsigAreas", _ ColPri(3), _ ColSec(3)

Page 13: Vb_Net_BD_2005_02

13

' Establecer condiciones de la restricción Restriccion.DeleteRule = Rule.Cascade Restriccion.UpdateRule = Rule.Cascade Restriccion.AcceptRejectRule = AcceptRejectRule.Cascade ' Añadir la restricción ObjDataSet.Tables("AlumnAsig").Constraints.Add(Restriccion) ' Establecer a True la propiedad EnforceConstraints, ' forzar las restricciones. ObjDataSet.EnforceConstraints = True End Sub

Todo lo referente al objeto lo podemos encontrar en el link: http://msdn2.microsoft.com/es-es/library/system.data.foreignkeyconstraint(VS.80).aspx

1.8 Definición de claves. El uso de las tablas conlleva la gestión de los registros y el control de las duplicidades y la localización

de los datos, para ello se hace necesario el uso de clave principal. Hay dos caminos para conseguirlo, uno es capturarlas de la base de datos, y el otro generarlas. Para las tablas existentes en la base de datos, lo suyo es capturarlo, OleDbDataAdpater.FillSchema, es

el método. Para las que se crean de forma provisional en el programa hay que crearlas. Veamos los dos sistemas. La captura de las claves de la tabla es sencilla. Try ObjDataSet.Tables("Titulos").Rows.Clear() ' limpia la tabla Catch ex As NullReferenceException Finally ' LLenar el adaptador Adaptador.Fill(Tabla) ' Capturar la clave desde la tabla Adaptador.FillSchema(Tabla, SchemaType.Source) End Try

Solo queda comentar que es la ejecución de la línea con el método FillSchema. Su utilización posteriormente puede ser como sigue en el ejemplo, en el cual se utiliza para realizar la

actualización del campo de entradas acumuladas. La explicación es : Creamos el array para la clave, es una clave de dos campos. Dim Clave(1) As Object

Asignamos los datos al array. Clave(0) = CType(Fila.Item("Tipo"), Object) Clave(1) = CType(Fila.Item("Codigo"), Object)

Creamos un objeto DataRow para capturar el registro existente con el método Find. Dim Registro As System.Data.DataRow Registro = ObjDataSet.Tables("Titulos").Rows.Find(Clave)

Page 14: Vb_Net_BD_2005_02

14

Si se encuentra se actualiza el dato, para ello se utiliza el valor del índice del registro leído. If Not (Registro Is Nothing) Then Cual = ObjDataSet.Tables("Titulos").Rows.IndexOf(Registro) SalAcu = CLng(Registro.Item("SalAcu").ToString) SalAcu = SalAcu + CLng(Fila.Item("Cantidad").ToString) ObjDataSet.Tables("Titulos").Rows(Cual).Item("Salacu") = SalAcu End If

Y el código completo. Private Sub ActualizarStock(ByVal Fila As DataRow) Dim Clave(1) As Object Dim SalAcu As Long Dim Cual As Integer Clave(0) = CType(Fila.Item("Tipo"), Object) Clave(1) = CType(Fila.Item("Codigo"), Object) Dim Registro As System.Data.DataRow Registro = ObjDataSet.Tables("Titulos").Rows.Find(Clave) Try If Not (Registro Is Nothing) Then Cual = ObjDataSet.Tables("Titulos").Rows.IndexOf(Registro) SalAcu = CLng(Registro.Item("SalAcu").ToString) SalAcu = SalAcu + CLng(Fila.Item("Cantidad").ToString) ObjDataSet.Tables("Titulos").Rows(Cual).Item("Salacu") = SalAcu End If Catch ex As OleDb.OleDbException MsgBox(ex.Message, MsgBoxStyle.Information, _ "Error en actualización stocks") End Try End Sub

La definición de una clave principal se realiza así, restricción de valor único llamado en VB. Se define el array y la clave. Dim ColPri(1) As DataColumn Dim Clave As UniqueConstraint

se le asigna los valores pertinentes. ColPri(0) = Tabla.Columns("Tipo") ColPri(1) = Tabla.Columns("Codigo")

se crea el objeto Clave, con el nombre “Principal”, indicando que es clave principal, “,True)”. Clave = New UniqueConstraint("Principal", ColPri, True)

Se añade a la tabla. Tabla.Constraints.Add(Clave)

Page 15: Vb_Net_BD_2005_02

15

Y todo completo queda. Private Sub CrearClave(ByVal Tabla As System.Data.DataTable) Dim ColPri(1) As DataColumn Dim Clave As UniqueConstraint ColPri(0) = Tabla.Columns("Tipo") ColPri(1) = Tabla.Columns("Codigo") Clave = New UniqueConstraint("Principal", ColPri, True) Tabla.Constraints.Add(Clave) End Sub

Lo referente a UniqueConstraint se puede acceder desde http://msdn2.microsoft.com/es-es/library/system.data.uniqueconstraint(VS.80).aspx

1.9 Transacción. Es el objeto que nos va a permitir realizar los procesos de actualización con la seguridad de poder

mantener la integridad de la base de datos. La definición y utilización del mismo es como sigue. ' Definición del objeto Dim Transaccion As System.Data.OleDb.OleDbTransaction ' Inicio de la transacción Transaccion = Conexion.BeginTransaction(IsolationLevel.Chaos) ' Final correcto de la transacción Transaccion.Commit() ' Final por error de la transacción, abortar. Transaccion.Rollback()

Solo queda integrar cada instrucción en el punto adecuado del programa. Cuando el proceso de transacción está en marcha, se ha de tener en cuenta no lanzarlo para un proceso

muy amplio, si no en unidades lógicas de actualización, no para un programa completo vamos. Como el proceso de actualización se ejecuta para varias tablas, cada una de esas tablas se actualiza

con su DataAdapter, y en cada uno de esos procesos de actualización es necesario la presencia de un objeto OleDbCommand, el objeto OleDbCommand necesita que se le pase el objeto Transacción que estemos utilizando en ese momento, por lo tanto el uso del objeto OleDbCommand quedaría como sigue:

' Cadena SQL Comando.CommandText = CadenaSQL ' Tipo de comando a ejecutar Comando.CommandType = CommandType.Text ' Conexión a utilizar, configurada previamente. Comando.Connection = Conexión ' Asignación del objeto transacción en curso. Comando.Transaction = Transaccion

Por lo tanto en el procedimiento de actualización de cada una de las tablas del programa hay que hacer

el cambio o que esté presente ' Asignación del objeto transacción en curso. Comando.Transaction = Transaccion

para su correcto funcionamiento. El ejemplo que sigue empieza comprobando si hay cambios en el DataSet.

Page 16: Vb_Net_BD_2005_02

16

If ObjDataSet.HasChanges Then

Después si es así, se entra en el proceso de actualizar. Se inicia la transacción. Conexion.Open() ' Inicio de la transacción Transaccion = Conexion.BeginTransaction(IsolationLevel.Chaos)

Se asigna cada OleDbCommand con el objeto conexión y con la transacción. Comando.Connection = Conexion Comando.Transaction = Transaccion

Se capturan los cambios en el DataSet copiándolos a un nuevo DataSet, en el ejemplo todos,

modificados, borrados e insertados. ObjDataSetCamb = ObjDataSet.GetChanges(DataRowState.Modified _ Or DataRowState.Added _ Or DataRowState.Deleted)

Después se repite tabla a tabla el proceso de actualización. Try AdapTitul.Update(ObjDataSetCamb.Tables("Titulos").GetChanges) ObjDataSet.Merge(ObjDataSet.Tables("Titulos")) ObjDataSet.AcceptChanges() Catch ex As ArgumentNullException Fallo = True End Try

Hasta llegar al final en el que se comprueba como ha ido, y se confirma o se aborta la transacción. If Not Fallo Then ' Final correcto de la transacción Transaccion.Commit() MsgBox("Base actualizada.", MsgBoxStyle.Information, _ "Actualizando dataset") Else ' Final por error de la transacción Transaccion.Rollback() MsgBox("Actualización abortada.", MsgBoxStyle.Critical, _ "Actualizando dataset") End If

Page 17: Vb_Net_BD_2005_02

17

El ejemplo es completo: Private Sub ActualizarBaseDatos(ByVal Fallo As Boolean) Dim Transaccion As System.Data.OleDb.OleDbTransaction Try Dim ObjDataSetCamb As New DataSet If ObjDataSet.HasChanges Then Conexion.Open() ' Inicio de la transacción Transaccion = Conexion.BeginTransaction(IsolationLevel.Chaos) Comando.Connection = Conexion Comando.Transaction = Transaccion ComTiTi.Connection = Conexion ComTiTi.Transaction = Transaccion ComTitu.Connection = Conexion ComTitu.Transaction = Transaccion ComMovi.Connection = Conexion ComMovi.Transaction = Transaccion ObjDataSetCamb = ObjDataSet.GetChanges(DataRowState.Modified _ Or DataRowState.Added _ Or DataRowState.Deleted) Try AdapTitul.Update(ObjDataSetCamb.Tables("Titulos").GetChanges) ObjDataSet.Merge(ObjDataSet.Tables("Titulos")) ObjDataSet.AcceptChanges() Catch ex As ArgumentNullException Fallo = True End Try If Not Fallo Then Try AdapMovim.Update(ObjDataSetCamb.Tables("Movimientos").GetChanges) ObjDataSet.Merge(ObjDataSet.Tables("Movimientos")) ObjDataSet.AcceptChanges() Catch ex As ArgumentNullException Fallo = True End Try End If If Not Fallo Then ' Final correcto de la transacción Transaccion.Commit() MsgBox("Base actualizada.", MsgBoxStyle.Information,”Actualizar") Else ' Final por error de la transacción Transaccion.Rollback() MsgBox("Actualización abortada.", MsgBoxStyle.Critical, "Actualizar") End If Conexion.Close() Else MsgBox("No se han realizado cambios", MsgBoxStyle.Information, _ "Actualizando dataset") End If Catch ex As System.Data.OleDb.OleDbException MsgBox(ex.Message, MsgBoxStyle.Information, "Actualizando dataset") End Try End Sub

Todo lo referente al objeto lo podemos encontrar en el link: http://msdn2.microsoft.com/es-es/library/system.transactions.transaction(VS.80).aspx