Download 1. Almacenamiento 1.1 Introducción. 1.2 DataTable.
Document related concepts
no text concepts found
Transcript
1. Almacenamiento 1.1 Introducción. Los objetos de almacenamiento son los nombrados, pero podríamos hacer alguna matización. El DataReader es simultáneamente las dos facetas del trabajo y si observamos el código, podemos observar que no se utiliza en su llenado el DataAdapter, porque la gestión de los datos la realiza dicho objeto. Por lo tanto podríamos ponerlo en los dos apartados, conexión y almacenamiento, pero nos ha parecido mejor este. El DataRow escapa a lo considerado como elemento de almacenar datos, pero su utilización facilita en mucho el manejo de datos, trasiego dentro de la aplicación, por lo tanto nos ha parecido adecuado nombrarlo. Todos los objetos pertenecen al System.Data, excepto el DataReader, que pertenece al System.Data.OleDb, podría ese ser un motivo para no incluirlo aquí, pero a pesar de eso pensamos que está mejor ubicado aquí. Escenarios de utilización, podemos encontrar dos básicamente. Trabajando en modo desconectado pero sin establecer un conjunto de datos propio en la aplicación, prescindir del DataSet. Trabajar en un modo desconectado, pero creando al inicio del programa correspondiente la estructura necesaria para el buen funcionamiento del mismo, creando un DataSet, para posteriormente volcar los datos en la base de datos. 1.2 DataTable. El espacio de nombres es System.Data.DataTable Hemos de tener en cuenta, que la utilización de una tabla con o sin un dataset no cambia en exceso. Pero sin embargo hay algunas cosas que no se permiten hacer. Veamos los pasos de un DataTable, desde un ejemplo de una tabla provisional de apoyo en el programa y en el ejemplo de una tabla de la base de datos. 1.2.1 Creación. La configuración de la conexión no cambia, es la vista con anterioridad. El proceso de carga que sigue parte de objetos definidos a nivel de formulario, o programa. Dim Dim Dim Dim Comando As New System.Data.OleDb.OleDbCommand Adaptador As OleDb.OleDbDataAdapter Tabla As System.Data.DataTable EnlaceTabla As New BindingSource ' Enlace La clave principal de esta tabla se crea en este procedimiento Private Sub CrearRestriccion(ByVal Tabla As System.Data.DataTable) Dim ColPri(1) As DataColumn Dim Restriccion As UniqueConstraint ' Unica ' Campos que componen la clave ColPri(0) = Tabla.Columns("Tipo") ColPri(1) = Tabla.Columns("Codigo") ' Se asignan a la restricción, y se índica que es clave principal. Restriccion = New UniqueConstraint("Principal", ColPri, True) ' Se añade a la tabla. Tabla.Constraints.Add(Restriccion) End Sub El ejemplo crea una tabla de datos provisional que se enlaza a un DataGridView, por eso la necesidad de que disponga de un campo de clave principal y única. Pasos seguidos Crear la referencia a la tabla. ' Se deshace de los datos anteriores Tabla = New DataTable El siguiente paso es crear la SQL, que como se puede observar es una tabla compuesta por datos de varios tablas, y que dado que el dato no existe quedará vacía, pero el datagrid cargará la cabecera. CadenaSql = "Select Movimientos.TipTitulo as Tipo, " & _ "Movimientos.Titulo as Codigo, " & _ "Titulos.Titulo, " & _ "Titulos.PreVenta as Precio, " & _ "Movimientos.Cantidad " & _ "From Movimientos " & _ "Inner Join Titulos On " & _ "(Movimientos.TipTitulo = Titulos.TipPub) and " & _ "(Movimientos.Titulo = Titulos.Codigo) " & _ "Where Movimientos.Numero = '" & Campo01.Text & "';" Generar el DataAdapter ' Crear un nuevo adaptador de datos Adaptador = New OleDb.OleDbDataAdapter(CadenaSql, Conexion) ' Llenar la tabla con los datos y enlazarza con el 'bindingsource' Adaptador.Fill(Tabla) Crear la clave principal. ' Se define la restricción CrearRestriccion(Tabla) El siguiente paso es el enlace con el datagrid. ' Se enlaza el objeto ObjDataGrid.DataSource = Tabla Cualquiera de los dos sistemas es válido. ' Se enlaza el objeto ObjDataGrid.DataSource = EnlaceTabla EnlaceTabla.DataSource = Tabla Las siguientes líneas se encargan de la configuración del DataGrid. Este es el código del ejemplo completo. Private Sub CargaDataGrid() Dim CadenaSql As String ' Se deshace de los datos anteriores Tabla = New DataTable CadenaSql = "Select Movimientos.TipTitulo as Tipo, " & _ "Movimientos.Titulo as Codigo, " & _ "Titulos.Titulo, " & _ "Titulos.PreVenta as Precio, " & _ "Movimientos.Cantidad " & _ "From Movimientos " & _ "Inner Join Titulos On " & _ "(Movimientos.TipTitulo = Titulos.TipPub) and " & _ "(Movimientos.Titulo = Titulos.Codigo) " & _ "Where Movimientos.Numero = '" & Campo01.Text & "';" Try Conexión.Open ' Crear un nuevo adaptador de datos Adaptador = New OleDb.OleDbDataAdapter(CadenaSql, Conexion) ' Llenar la tabla con los datos y enlazarza con el 'bindingsource' Adaptador.Fill(Tabla) ' Se define la restricción CrearRestriccion(Tabla) ' Se enlaza el objeto ObjDataGrid.DataSource = Tabla ‘ Configurar el DataGrid ConfigDataGrid(Me, ObjDataGrid, False) ObjDataGrid.Columns(0).Width = CInt(ObjDataGrid.Width * 0.08) ObjDataGrid.Columns(1).Width = CInt(ObjDataGrid.Width * 0.1) ObjDataGrid.Columns(2).Width = CInt(ObjDataGrid.Width * 0.5) ObjDataGrid.Columns(3).Width = CInt(ObjDataGrid.Width * 0.1) ObjDataGrid.Columns(3).DefaultCellStyle.Alignment = _ DataGridViewContentAlignment.MiddleRight ObjDataGrid.Columns(4).Width = CInt(ObjDataGrid.Width * 0.12) ObjDataGrid.Columns(4).DefaultCellStyle.Alignment = _ DataGridViewContentAlignment.MiddleRight Catch ex As OleDb.OleDbException MsgBox(ex.Message, MsgBoxStyle.Information) End Try Conexión.Close End Sub 1.2.2 Actualización. El proceso de la actualización pasa por la localización primero del registro que nos interesa. Para ello utilizamos el método Find y le proporcionamos un valor acorde con el campo de clave definido en la tabla. También se puede realizar la actualización a partir del objeto que se ha enlazado a la tabla, desde un DataGridView, sería lo más sencillo, como se ha visto antes. El método del DataGrid solo requiere que el objeto se haya enlazado en el momento de la carga de la tabla, como vemos en el ejemplo, o mediante el BindingSource. ' Se enlaza el objeto ObjDataGrid.DataSource = Tabla Y después solo se trata de dejar que se pueda editar en el DataGrid, Para ello hay que actuar sobre estas propiedades convenientemente. ObjDataGrid.AllowUserToAddRows = True ObjDataGrid.AllowUserToDeleteRows = True ObjDataGrid.AllowUserToOrderColumns = True ObjDataGrid.EditMode = DataGridViewEditMode.EditOnEnter ObjDataGrid.ReadOnly = False El sistema de la búsqueda en la tabla es el que sigue. 1.2.3 Borrado. Se trata de generar un objeto registro que exista y después utilizar el método remove del objeto dataTable. Dim Clave(1) As Object Clave(0) = “01” Clave(1) = “0002” Dim Registro As System.Data.DataRow = _ ObjDataSet.Tables("Clientes").Rows.Find(Clave) Tabla.Rows.Remove(Registro) Este es otro ejemplo tomado de la documentación de Microsoft, que tiene la ventaja de utilizar más recursos y comprobar que existe. Dim Registros As DataRowCollection = Tabla.Rows ' Control de la existencia del dato If Registros.Contains(“0001”) Then Dim RegistroExistente As DataRow = Registros.Find(“0001”) Registros.Remove (RegistroExistente) End If Otra posibilidad es la de hacerlo desde el objeto de visualización enlazado, en cuyo caso sería ObjDataGrid.Rows.Remove(ObjDataGrid.CurrentRow) Que traducido significa que borramos la fila actual del DataGrid, que como está enlazado a la tabla, se efectúa en la tabla también. 1.2.4 Adición. tabla. Para añadir un registro creamos un objeto DataRow, al que asignaremos los datos del registro de la Posteriormente el objeto DataRow se añade a la tabla. Primer paso, crear el objeto, usamos el método NewRow, el cual nos devuelve un registro vacío con la estructura de la tabla. Dim Registro As DataRow = Tabla.NewRow El siguiente paso es asignar los datos al registro que hemos creado. Registro.Item("Tipo") = Titulo.Codigo.ToString Registro.Item("Codigo") = Titulo.Codig2.ToString La asignación podría hacerse por el índice del campo, es mejor utilizar el nombre del campo en la tabla, es más seguro, pues no depende del cambio de orden en la Select. Después de haber asignado los datos, añadir el registro a la tabla. Tabla.Rows.Add(Registro) La captura de errores, permitirá el control de duplicados, ya que antes hemos definido la clave principal. El código completo es el que sigue. Private Sub AnyadirTitulos(ByRef Tabla as System.Data.DataTable) Dim Registro As DataRow = Tabla.NewRow Dim Titulo As ItemLista = CType(Lista04.SelectedItem, ItemLista) Dim RegTit As System.Data.DataRow Registro.Item("Tipo") = Titulo.Codigo.ToString Registro.Item("Codigo") = Titulo.Codig2.ToString Registro.Item("Titulo") = Titulo.ToString Registro.Item("Cantidad") = "0" Registro.Item("Precio") = Titulo.Codig3 Try Tabla.Rows.Add(Registro) Catch ex As ConstraintException MsgBox("Título existente", MsgBoxStyle.Critical, NomProgram) End Try End Sub La otra posibilidad que se puede presentar es la de añadir datos a una tabla de la base de datos con una instrucción SQL Los pasos a seguir son generar la instrucción SQL a utilizar, del tipo Insert Into, asignar dicha instrucción SQL a un objeto OleDbCommand. En este objeto después utilizaremos el método ExecuteNonQuery, para enviar el registro a la base de datos. Crear la instrucción SQL CadenaSQL = "INSERT INTO Movimientos ( Fecha, Tipo, Codigo, " & _ "TipTitulo, Titulo, TipMov, Cantidad, " & _ "FacAbo, Numero ) " & _ "Values ('" & Fech & "', " & _ "'" & TiCl & "', " & _ "'" & CoCl & "', " & _ "'" & TipT & "', " & _ "'" & Titu & "', " & _ "'" & TiMv & "', " & _ "'" & Cant & "', " & _ "'0', " & _ "'" & Nume & "') " Generar los parámetros del objeto OleDbCommand, que es el que realizará la tarea. ' 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 La ejecución se basa en la captura de cuantos registros se ven afectados por la ejecución del método, comprobando en este caso que es cero o distinto de cero según interese. Cuantos = Comando.ExecuteNonQuery Fallo = Cuantos = 0 En este caso se asigna el valor a la variable Booleana Fallo que tomará cierto o true según proceda. El ejemplo completo es el que sigue. Private Sub GrabarMovim( _ ByVal Conexion As System.Data.OleDb.OleDbConnection, _ ByRef Comando As System.Data.OleDb.OleDbCommand, _ ByVal Fech As String, _ ByVal TiCl As String, _ ByVal CoCl As String, _ ByVal TipT As String, _ ByVal Titu As String, _ ByVal Cant As String, _ ByVal Nume As String, _ ByRef Fallo As Boolean) Dim Cuantos As Integer Dim TiMv As String = "3" ' entradas de almacen por devolución de cliente Dim CadenaSQL As String CadenaSQL = "INSERT INTO Movimientos ( Fecha, Tipo, Codigo, " & _ "TipTitulo, Titulo, TipMov, Cantidad, " & _ "FacAbo, Numero ) " & _ "Values ('" & Fech & "', " & _ "'" & TiCl & "', " & _ "'" & CoCl & "', " & _ "'" & 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 1.2.5 Relaciones y Claves. Fuera de un DataSet no es posible crear relaciones. La clave principal si es posible crearla. Es similar al ejemplo de un DataSet. 1.2.5.1 Cargándola desde la tabla de la base de datos. En el caso de cargarla desde el diseño de la base de datos, solo hay que utilizar el método FillSchema Adaptador.Fill(Tabla) Adaptador.FillSchema(Tabla, SchemaType.Source) Es así de sencillo, con éste paso la tabla queda cargada con su clave principal. 1.2.5.2 Generándola en el programa. La otra posibilidad es generarla en el programa, sobre todo es útil cuando se trabaja con una tabla temporal. Private Sub CrearRestriccion(ByVal Tabla As System.Data.DataTable) Dim ColPri(1) As DataColumn Dim Restriccion As UniqueConstraint ' Unica ' Campos que componen la clave ColPri(0) = Tabla.Columns("Tipo") ColPri(1) = Tabla.Columns("Codigo") ' Se asignan a la restricción, y se índica que es clave principal. Restriccion = New UniqueConstraint("Principal", ColPri, True) ' Se añade a la tabla. Tabla.Constraints.Add(Restriccion) End Sub Todo lo referente al objeto DataTable podemos encontrarlo en el siguiente Link. http://msdn2.microsoft.com/es-es/library/system.data.datatable(VS.80).aspx 1.3 DataSet. El espacio de nombres es System.Data.DataSet Este objeto permite crear un subconjunto de los datos de una base de datos, para su uso local. Esto implica que al principio del programa se ha de crear un procedimiento que permita cargar los datos desde la base de datos para su utilización en el mismo. Posteriormente desde las tablas de este DataSet, se pueden llenar con datos los objetos del programa, sin necesidad ya de acceder a la base de datos, ni de abrir una conexión con la misma. Podemos añadir o borrar datos de dichas tablas y realizar la posterior actualización en la misma. Veamos estos pasos. 1.3.1 Creación del DataSet. La configuración de la conexión no cambia, es la vista con anterioridad. El proceso de carga que sigue parte de objetos definidos a nivel de formulario, o programa. En este primer ejemplo se carga una sola tabla, y el esquema de clave se genera en el mismo procedimiento. Los objetos a utilizar son Dim ObjDataSet As System.Data.DataSet Dim Comando As New System.Data.OleDb.OleDbCommand Dim ComanAct As New System.Data.OleDb.OleDbCommandBuilder Dim Dim Dim Dim Adaptador AdapTitul AdapAlbCa AdapAlbDe As As As As New New New New OleDb.OleDbDataAdapter OleDb.OleDbDataAdapter OleDb.OleDbDataAdapter OleDb.OleDbDataAdapter Dim Tabla As System.Data.DataTable El procedimiento es el que sigue. Private Sub CrearDataSet() ObjDataSet = New System.Data.DataSet Dim CadenaSQL As String Dim ClavePri(1) As DataColumn CadenaSQL = "Select * " & _ "From Titulos " & _ "Order by Titulos.TipPub, Titulos.Codigo " Try ' Abrir la base de datos. Conexion.Open() Comando = New System.Data.OleDb.OleDbCommand AdapTitul = New System.Data.OleDb.OleDbDataAdapter Tabla = New Data.DataTable ' Tipo de comando a ejecutar Comando.CommandType = CommandType.Text ' Genera el código SQL para la actualización ComanAct = New OleDb.OleDbCommandBuilder(AdapTitul) ' Contenido del comando Comando.CommandText = CadenaSQL ' Conexión a utilizar, configurada previamente. Comando.Connection = Conexion ' Asignación del comando al objeto adapter. AdapTitul.SelectCommand = Comando ' LLenar el adaptador Try ' Solo si procede. ' ObjDataSet.Tables("Titulos").Rows.Clear() ' limpia la tabla Catch ex As NullReferenceException Finally AdapTitul.Fill(Tabla) End Try ' Establece la clave primaria. ClavePri(0) = Tabla.Columns.Item("TipPub") ClavePri(1) = Tabla.Columns.Item("Codigo") Tabla.PrimaryKey() = ClavePri Tabla.TableName = "Titulos" ObjDataSet.Tables.Add(Tabla) Catch Ex As Exception MsgBox(Ex.Message, MsgBoxStyle.Information, _ "Crear tabla títulos en dataset ") End Try End Sub Este paso se repetiría para cada una de las tablas que tengamos en la base de datos, y que deseemos incluir en el DataSet. En el ejemplo que sigue se hace la carga de dos tablas, utilizando dos sistemas distintos para la creación de la clave principal. El cambio es concretamente el que figura a continuación, después figura en el ejemplo completo. ' Captura de la clave de la tabla desde la tabla de la base de datos. AdapAlbCa.FillSchema(Tabla, SchemaType.Source) ' Llenado de la tabla desde la base de datos AdapAlbCa.Fill(Tabla) Como podemos observar es solo el uso del método FillSchema del objeto DataAdapter, con los parámetros que se especifican. El código que sigue podría estar en el mismo procedimiento a continuación del anterior. Private Sub CrearDataSet() ObjDataSet = New System.Data.DataSet Dim CadenaSQL As String Dim ClavePri(1) As DataColumn CadenaSQL = "Select * From AlbDetalle Order by NumAlb, Linea" Try Comando = New System.Data.OleDb.OleDbCommand AdapAlbDe = New System.Data.OleDb.OleDbDataAdapter Tabla = New Data.DataTable ' Tipo de comnndo a ejecutar Comando.CommandType = CommandType.Text ' Genera el código SQL para la actualización ComanAct = New OleDb.OleDbCommandBuilder(AdapAlbDe) ' Contenido del comando Comando.CommandText = CadenaSQL ' Conexión a utilizar, configurada previamente. Comando.Connection = Conexion ' Asignación del comando al objeto adapter. AdapAlbDe.SelectCommand = Comando ' LLenar el adaptador Try ' ObjDataSet.Tables("AlbDetalle").Rows.Clear() ' limpia la tabla Catch ex As NullReferenceException Finally AdapAlbDe.Fill(Tabla) End Try ReDim ClavePri(1) 'As DataColumn ' Establece la clave primaria. ClavePri(0) = Tabla.Columns.Item("NumAlb") ClavePri(1) = Tabla.Columns.Item("Linea") Tabla.PrimaryKey() = ClavePri Tabla.TableName = "AlbDetalle" ObjDataSet.Tables.Add(Tabla) Catch Ex As Exception MsgBox(Ex.Message, MsgBoxStyle.Information, _ "Crear tabla Albarán Detalle Dataset ") End Try CadenaSQL = "Select * From AlbCab Order by NumAlb" Try Comando = New System.Data.OleDb.OleDbCommand AdapAlbCa = New System.Data.OleDb.OleDbDataAdapter Tabla = New Data.DataTable ' Tipo de comnndo a ejecutar Comando.CommandType = CommandType.Text ' Genera el código SQL para la actualización ComanAct = New OleDb.OleDbCommandBuilder(AdapAlbCa) ' Contenido del comando Comando.CommandText = CadenaSQL ' Conexión a utilizar, configurada previamente. Comando.Connection = Conexion ' Asignación del comando al objeto adapter. AdapAlbCa.SelectCommand = Comando ' LLenar el adaptador Try 'ObjDataSet.Tables("AlbCab").Rows.Clear() ' limpia la tabla Catch ex As NullReferenceException Finally ' Cambio en la forma de crear la clave principal ' Captura de la clave de la tabla desde la tabla de la base de datos. AdapAlbCa.FillSchema(Tabla, SchemaType.Source) ' Llenado de la tabla desde la base de datos AdapAlbCa.Fill(Tabla) End Try ReDim ClavePri(0) ' Establece la clave primaria, este es el cambio ClavePri(0) = Tabla.Columns.Item("NumAlb") Tabla.PrimaryKey() = ClavePri Tabla.TableName = "AlbCab" ObjDataSet.Tables.Add(Tabla) Catch Ex As Exception MsgBox(Ex.Message, MsgBoxStyle.Information, _ "Crear tabla Albarán Cabecera Dataset ") End Try Conexion.Close() End Sub 1.3.2 Añadido de datos a la tabla del DataSet. El ejemplo que sigue añade un registro nuevo a la tabla de un DataSet. Se reciben los datos que se van a insertar y se asignan a un objeto DataRow, que posteriormente se añade a la tabla. Veamos en detalle. Primero definir el objeto DataRow. Dim Registro As DataRow = ObjDataSet.Tables("AlbCab").NewRow En el paso anterior se carga también la estructura del registro, por lo que ahora solo queda Registro.Item("NumAlb") = NumAlb Registro.Item("Fecha") = Fecha Registro.Item("TipCli") = TipoCli Una vez asignados los datos, solo queda añadir el registro a la tabla del DataSet. ObjDataSet.Tables("AlbCab").Rows.Add(Registro) El código completo es el que sigue. Private Sub GrabarCabAlbaran(ByVal ByVal ByVal ByVal ByVal NumAlb As String, _ FecAlb As String, _ TipoCli As String, _ CodCli As String, _ Pedido As String) Dim Registro As DataRow = ObjDataSet.Tables("AlbCab").NewRow Dim Fecha As String = FecAlb Fecha = Strings.Right(Fecha, 4) Strings.Left(Fecha, 2) Try Registro.Item("NumAlb") = NumAlb Registro.Item("Fecha") = Fecha Registro.Item("TipCli") = TipoCli Registro.Item("CodCli") = CodCli Registro.Item("NumPed") = Pedido Registro.Item("Impres") = 1 Registro.Item("Factu") = 0 & Strings.Mid(Fecha, ObjDataSet.Tables("AlbCab").Rows.Add(Registro) Catch ex As ConstraintException MsgBox("Albaran existente en cabecera ", NomProgram) End Try End Sub 4, 2) & MsgBoxStyle.Critical, Finalizado este paso, al acabar la ejecución del programa se actualizará la base de datos. 1.3.3 Búsqueda y actualización de datos en la tabla del DataSet. En el ejemplo que sigue se reciben los datos que se van a usar en un registro de una tabla, por lo que fila es del tipo DataRow. Veamos los pasos. Generamos el objeto que nos va a servir como clave principal para la búsqueda. Dim Clave(1) As Object El siguiente paso es asignar los valores a éste array, los datos se obtienen del objeto Fila recibido. Clave(0) = CType(Fila.Item("Tipo"), Object) Clave(1) = CType(Fila.Item("Codigo"), Object) El siguiente paso es generar un objeto registro, para usarlo en la actualización y cargarlo con datos en la búsqueda, no se usa NewRow, porque buscamos un registro que sabemos que existe, y usamos el método Find. Dim Registro As System.Data.DataRow = _ ObjDataSet.Tables("Titulos").Rows.Find(Clave) A pesar de todo se comprueba que existe If Not (Registro Is Nothing) Then Y si procede se guarda la dirección del registro en la tabla, Cual = ObjDataSet.Tables("Titulos").Rows.IndexOf(Registro) para a continuación realizar el proceso de actualización SalAcu = CLng(Registro.Item("SalAcu").ToString) SalAcu = SalAcu + CLng(Fila.Item("Cantidad").ToString) y grabar los datos en la posición conocida. ObjDataSet.Tables("Titulos").Rows(Cual).Item("Salacu") = SalAcu El código completo a continuación. 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 = _ 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 No hay que utilizar ObjDataSet.Tables("Titulos").Rows(Cual).SetModified() porque ya se queda como fila modificada, al haberla actualizado. Tampoco hay que utilizar ObjDataSet.Tables("Titulos").AcceptChanges() porque en ese caso desactivaríamos al registro como modificado y entonces al realizar el proceso de actualización en la base de datos, no se produciría la actualización en la base de datos de origen. 1.3.4 Actualización de la base de datos. El ejemplo que sigue es un procedimiento completo de actualización de los datos que se han modificado en el DataSet sobre la base de datos. Veámoslo por bloques El primer paso es generar un objeto DataSet que asuma los cambios que ha habido en el que se utiliza en el programa Dim ObjDataSetCamb As New DataSet datos. El siguiente paso es condicionar la actualización a que se haya producido algún cambio en la base de If ObjDataSet.HasChanges Then A continuación se pasa los cambios del DataSet del programa al nuevo DataSet, definiendo que tipos de cambios deseamos que se procesen. ObjDataSetCamb = ObjDataSet.GetChanges(DataRowState.Modified _ Or DataRowState.Added _ Or DataRowState.Deleted) Realizado este paso, ahora ya es ir tabla a tabla y actualizar su contenido en la base de datos. AdapTitul.Update(ObjDataSetCamb.Tables("Titulos").GetChanges) ObjDataSet.Merge(ObjDataSet.Tables("Titulos")) ObjDataSet.AcceptChanges() Private Sub ActualizarBaseDatos() Try Dim ObjDataSetCamb As New DataSet If ObjDataSet.HasChanges Then Conexion.Open() 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 End Try Try AdapMovim.Update(ObjDataSetCamb.Tables("Movimientos").GetChanges) ObjDataSet.Merge(ObjDataSet.Tables("Movimientos")) ObjDataSet.AcceptChanges() Catch ex As ArgumentNullException End Try Try AdapAlbCa.Update(ObjDataSetCamb.Tables("AlbCab").GetChanges) ObjDataSet.Merge(ObjDataSet.Tables("AlbCab")) ObjDataSet.AcceptChanges() Catch ex As ArgumentNullException End Try Try AdapAlbDe.Update(ObjDataSetCamb.Tables("AlbDetalle").GetChanges) ObjDataSet.Merge(ObjDataSet.Tables("AlbDetalle")) ObjDataSet.AcceptChanges() Catch ex As ArgumentNullException End Try Try AdapClien.Update(ObjDataSetCamb.Tables("Clientes").GetChanges) ObjDataSet.Merge(ObjDataSet.Tables("Clientes")) ObjDataSet.AcceptChanges() Catch ex As ArgumentNullException End Try Conexion.Close() CrearDataSet() MsgBox("Base actualizada.", MsgBoxStyle.Information, _ "Actualizando dataset") 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 1.3.5 Carga de objetos. El siguiente paso una vez que se ha generado el DataSet, o se ha credo la estructura local de la base de datos, es explotarla, empecemos obteniendo datos de la misma, usando un listbox para cargarlo. Observemos que no se utiliza la conexión, pues no hace falta. El ejemplo que sigue funciona correctamente, pero falta comparar su eficacia con respecto al otro ejemplo que hay después. El motivo de ponerlo es debido a como parece que funciona las relaciones entre las tablas, pues se basa en realidad en listas de datos en memoria, a las que suponemos se acude para tomar los datos que cumplen la condición y obtener los datos. Por lo tanto podría ser que realizando un acceso con el método Find, y luego el código que aquí exponemos, fuera igual de rápido, y al menos queda una forma más de usar los datos en el DataSet. El sistema no es más que una búsqueda secuencial, que hay que optimizar. Private Sub CargaListaTitulo(ByRef Lista As ListBox, _ ByVal Tipo As String) Dim Comando As New System.Data.OleDb.OleDbCommand Dim Objeto As ItemLista Dim Fila As System.Data.DataRow Dim X As Integer Lista.Items.Clear() ' Vaciar la lista X = 0 Try ' Recorrido de la tabla While X < ObjDataSet.Tables("Titulos").Rows.Count ' Obtención de un registro Fila = ObjDataSet.Tables("Titulos").Rows(X) ' Filtrado Select Case Fila.Item("TipPub").ToString = Tipo Case True Objeto = New ItemLista(Trim(Fila.Item("Titulo").ToString), _ Fila.Item("TipPub").ToString, Fila.Item("Codigo").ToString) Lista.Items.Add(Objeto) End Select X = X + 1 End While Catch ex As OleDb.OleDbException MsgBox(ex.Message, MsgBoxStyle.Information, "Leer dataset títulos") End Try End Sub Este otro está mas de acorde con la filosofía del lenguaje. Se basa en el uso del objeto DataView, que obtiene relaciones de datos de una tabla pudiendo filtrarlos por el contenido de un campo, y estableciendo cual deseamos usar para la clasificación. ' campo a usar en el filtro ObjDataView.RowFilter = "TipPub = '" & Tipo & "'" Además permite obtener los datos de una tabla seleccionando los que se han modificado, los que se han eliminado, etc. ObjDataView.RowStateFilter = DataViewRowState.CurrentRows Después solo queda pasar los datos del DataView a la lista. Private Sub CargaListaTitulosDataSet(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(ObjDataSet.Tables("Titulos")) ' Definir parámetros With ObjDataView ' Asignación de la tabla .Table = ObjDataSet.Tables("Titulos") .AllowDelete = False .AllowEdit = False .AllowNew = False ' campo a usar en el filtro .RowFilter = "TipPub = '" & Tipo & "'" .RowStateFilter = DataViewRowState.CurrentRows ' campo a usar para la ordenación .Sort = "Titulo" End With Lista.Items.Clear() ' Asignación de los datos al listbox For X = 0 To ObjDataView.Count - 1 Objeto = New _ ItemLista(Trim(ObjDataView(X).Row.Item("Titulo").ToString), _ ObjDataView(X).Row.Item("TipPub").ToString, _ ObjDataView(X).Row.Item("Codigo").ToString, _ ObjDataView(X).Row.Item("PreVenta").ToString) Lista.Items.Add(Objeto) Next End Sub Todo lo referente a este objeto podemos encontrarlo en el siguiente Link. http://msdn2.microsoft.com/es-es/library/system.data.dataset(VS.80).aspx 1.4 DataReader. El espacio de nombres es System.Data.OleDb.OleDbDataReader El uso de este objeto es muy sencillo, quizás el único problema que se puede presentar, pero que si no se hacen pruebas con grandes volúmenes de datos no se sabe, es el tiempo que pueda requerir para su uso en la conexión que no sea un gran inconveniente. El ejemplo que exponemos carga una lista de datos ElementoLista. Los pasos seguidos son: Definir el objeto Dim Reader As System.Data.OleDb.OleDbDataReader Generar la cadena SQL que se va a usar en la consulta. CadenaSQL = "Select Codigo, Nombre From Autores Order By Nombre" Abrir la conexión ' Abrir la base de datos. Conexion.Open() Definir el objeto OleDbCommand ' Contenido del comando Comando.CommandText = CadenaSQL ' Tipo de comando a ejecutar Comando.CommandType = CommandType.Text ' Conexión a utilizar, configurada previamente. Comando.Connection = Conexion Ejecutar el objeto OleDbCommand, el cual asigna el resultado al objeto Reader. ' Ejecución de SQL Reader = Comando.ExecuteReader Después solo queda el ejecutar el bucle mientras haya posibilidad de leer, antes Not EOF. While Reader.Read Objeto = New ElementoLista(Trim(Reader.Item("Nombre").ToString), _ Reader.Item("Codigo").ToString) Lista.Items.Add(Objeto) End While Los datos quedan almacenados en la colección Item del DataReader. El acceso es mejor hacerlo por nombre de campo, que por índice. 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 ElementoLista 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 comando 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 ElementoLista(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 El objeto Reader, tiene una peculiaridad de la que hay que acordarse, y es que While Reader.Read Es simultáneamente lectura y condición, antes teníamos el EOF. El ejemplo ha sido en una carga para un listbox, pero se puede usar para un listado, para cualquier proceso que no requiera actualizaciones, solo lectura, y que deseemos que sea rápido. Todo lo referente a este objeto podemos encontrarlo en el siguiente Link. http://msdn2.microsoft.com/es-es/library/system.data.oledb.oledbdatareader(VS.80).aspx 1.5 DataRow. El espacio de nombres es System.Data.DataRow El objeto DataRow posee la estructura de un registro de la tabla. Se puede generar A partir de la estructura de una tabla que ya existe en el programa, bien en DataSet o DataTable. Dim Registro As DataRow = ObjDataSet.Tables("Tablagrid").NewRow Como registro cargado con datos a partir de la asignación de un registro existente en una tabla. Dim Registro As System.Data.DataRow Registro = ObjDataSet.Tables("Titulos").Rows.Find(Clave) Los datos del objeto están accesibles en la colección Item. El acceso es mejor hacerlo por nombre de campo, que por índice. Registro.Item("Tipo") = Titulo.Codigo.ToString Registro.Item(0) = Titulo.Codigo.ToString Estas dos líneas son equivalentes, pues en la línea en la que se genera la tabla, el campo “Tipo” ocupa el primer lugar, pero es más seguro por nombre, pues si por cualquier motivo se cambia el orden en la Select, no pasaría nada. Esta colección se puede recorrer con un índice si es necesario. Una vez que hemos creado el objeto su utilización es como sigue. Registro.Item("Tipo") = Titulo.Codigo.ToString Registro.Item("Codigo") = Titulo.Codig2.ToString Registro.Item("Titulo") = Titulo.ToString Registro.Item("Cantidad") = "10" Registro.Item("Precio") = Titulo.Codig3.ToString Try ObjDataSet.Tables("tablaGrid").Rows.Add(Registro) Catch ex As ConstraintException MsgBox("Título existente", MsgBoxStyle.Critical, NomProgram) End Try En éste ejemplo se asignan datos a los campos del registro, y éste después se asigna a la tabla, controlando la posible duplicidad de los datos en la misma. El paso contrario es Dim Dato as String Dato = Registro.Item("Tipo").ToString Todo lo referente a este objeto podemos encontrarlo en el siguiente Link. http://msdn2.microsoft.com/es-es/library/system.data.datarow(VS.80).aspx