Formulario de datos

08/08/2006 - 20:11 por Francisco Garzon | Informe spam
Hola grupo, saludos a todos.

Estoy intentando realizar mi primer programa en serio con el vb.net, he
contruido un formulario para acceder a la tabla de clientes de una base de
datos llamada GESTION. Os explico un poco como lo estoy haciendo y despues
os muestro mi problema:

Tengo el siguiente codigo en el evento Load:

strConn = "Server=(Local);DataBase=GESTION;Integrated Security=SSPI"
Dim CNN As New SqlConnection(strConn)

Dim strSQL As String = "SELECT * FROM Customers"
Dim scmd As New SqlCommand(strSQL, CNN)

sda = New SqlDataAdapter(scmd)

Dim scb As New SqlCommandBuilder(sda)
sda.InsertCommand = scb.GetInsertCommand()
sda.UpdateCommand = scb.GetUpdateCommand()
sda.DeleteCommand = scb.GetDeleteCommand()

dsPrincipal = New DataSet()
sda.Fill(dsPrincipal, "Customers")
dtPrincipal = dsPrincipal.Tables(0)

txtID.DataBindings.Add("Text", dtPrincipal, "ID")
txtApellidos.DataBindings.Add("Text", dtPrincipal, "Apellidos")
txtNombre.DataBindings.Add("Text", dtPrincipal, "Nombre")


Para moverme por los registros utilizo botones con el codigos:

Me.BindingContext(dtPrincipal).Position -= 1

ó

Me.BindingContext(dtPrincipal).Position += 1


Para actualizar:

Me.BindingContext(dtPrincipal).EndCurrentEdit()
sda.Update(dtPrincipal)

Para Cancelar:

Me.BindingContext(dtPrincipal).CancelCurrentEdit()
sda.Update(dtPrincipal)


Y todo hasta aqui bien, modifico los textbox y cuando ejecuto el boton
actualizar o cancelar me funciona perfectamente.

En cambio para crear un nuevo registro utilizo lo siguiente:

Me.BindingContext(dtPrincipal).AddNew()

se me limpian los textbox y tecleo los nuevos datos completos. Al pulsar el
boton de actualizar con el codigo que hemos visto antes me salta una
excepcion indicandome que el campo ID es obligatorio y no puede contener
null, borrandome el que yo habia tecleado.

Alguien me puede decir que estoy haciendo mal, y si existe una forma mejor
de hacer los que estoy haciendo, que no sea con el asistente para acceso a
datos, por favor que me lo diga.


Otra pregunta, ¿Para que sirven las siguientes lineas, ya que si las quito
tambien funciona?, ¿Son necesarias?

Dim scb As New SqlCommandBuilder(sda)
sda.InsertCommand = scb.GetInsertCommand()
sda.UpdateCommand = scb.GetUpdateCommand()
sda.DeleteCommand = scb.GetDeleteCommand()

Tambien me gustaria saber que debo ejecutar cuando cierre el formulario y
cerrar todos las conexiones abiertas, dataadapter, dataset, datatable, ...

Como siempre, muchisimas gracias de antemano.

Saludos

Preguntas similare

Leer las respuestas

#1 SoftJaén
08/08/2006 - 21:20 | Informe spam
"Francisco Garzon" escribió:

En cambio para crear un nuevo registro utilizo lo siguiente:

Me.BindingContext(dtPrincipal).AddNew()

se me limpian los textbox y tecleo los nuevos datos completos. Al pulsar
el boton de actualizar con el codigo que hemos visto antes me salta una
excepcion indicandome que el campo ID es obligatorio y no puede contener
null, borrandome el que yo habia tecleado.



Hola, Francisco:

Si el campo ID es la clave principal de la tabla, o es un campo requerido,
necesariamente tendrás que indicar un valor para dicho campo, porque de lo
contrario, obtendrás la excepción que nos has comentado.

existe una forma mejor de hacer los que estoy haciendo,
que no sea con el asistente para acceso a datos



Si deseas tener un formulario enlazado a datos, en lugar de utilizar los
Asistentes, escribe el código fuente necesario.

En el siguiente enlace te lo explico. Lo único que tienes que hacer es
cambiar los objetos del espacio de nombre OleDb, por los mismos objetos
correspondientes al espacio de nombres SqlClient:

Cómo crear un enlace de datos en tiempo de ejecución
http://mvp-access.com/softjaen/base...onet08.htm

¿Para que sirven las siguientes lineas, ya que si las quito
tambien funciona?, ¿Son necesarias?

Dim scb As New SqlCommandBuilder(sda)
sda.InsertCommand = scb.GetInsertCommand()
sda.UpdateCommand = scb.GetUpdateCommand()
sda.DeleteCommand = scb.GetDeleteCommand()



Esos comandos sirven para generar automáticamente los objetos Command
necesarios para insertar, actualizar y eliminar registros, y aunque los
elimines te funciona porque estás trabajando con una sola tabla, que
seguramente no estará relacionada con otra tabla mediante un diagrama.

Tambien me gustaria saber que debo ejecutar cuando cierre el formulario y
cerrar todos las conexiones abiertas, dataadapter, dataset, datatable, ...



Si el formulario que deseas cerrar, lo has abierto de manera «modal», puedes
llamar a su método «Dispose», si deseas que se destruya inmediatamente, cosa
ésta que se hará automáticamente cuando cierres el formulario principal y
por tanto la aplicación.

En cuanto al cierre de conexiones, lo recomendado es que la tengas abierta
el tiempo suficiente para abrir o actualizar un origen de los datos, y
establezcas su valor a «Nothing» (al igual que los restantes objetos que
comentas), cuando no los vayas a utilizar más, para que de ésta manera, se
eliminen definitivamente del montón administrado, cuando se ejecute el
recolector de elementos no utilizados.

Un saludo

Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.
Respuesta Responder a este mensaje
#2 Francisco
09/08/2006 - 08:48 | Informe spam
Hola, Enrique. En principio gracias por las respuestas.

En el primer caso, efectivamente el campo ID es clave y no puede estar a
NULL, pero el problema es que se lo especifico en el textbox txtID que esta
enlazado de la siguiente manera:

txtID.DataBindings.Add("Text", dtPrincipal, "ID")

pero no me tiene en cuenta el valor introducido y lo borrar de la caja de
texto.
En cambio en los otros campos parece que va bien.

Tambien he estado viendo el link que me dices y me surge una duda en el
metodo update.
Si rellenas el ds con la nueva consulta, ¿no se pierden las modificaciones
que habias realizado antes?

' Rellenamos el objeto DataSet con los datos
' de la consulta SQL
da.Fill(ds, tableName)

...

' Enviamos los cambios a la base de datos
da.Update(ds, tableName)

y cuando se envie los datos a la base de dato no enviara los ultimos
obtenido, ya que los modificados en el ds se han perdido??

Saludos.

From: "SoftJaén"
Newsgroups: microsoft.public.es.dotnet.vb
Sent: Tuesday, August 08, 2006 9:20 PM
Subject: Re: Formulario de datos


"Francisco Garzon" escribió:

En cambio para crear un nuevo registro utilizo lo siguiente:

Me.BindingContext(dtPrincipal).AddNew()

se me limpian los textbox y tecleo los nuevos datos completos. Al pulsar
el boton de actualizar con el codigo que hemos visto antes me salta una
excepcion indicandome que el campo ID es obligatorio y no puede contener
null, borrandome el que yo habia tecleado.



Hola, Francisco:

Si el campo ID es la clave principal de la tabla, o es un campo requerido,
necesariamente tendrás que indicar un valor para dicho campo, porque de lo
contrario, obtendrás la excepción que nos has comentado.

existe una forma mejor de hacer los que estoy haciendo,
que no sea con el asistente para acceso a datos



Si deseas tener un formulario enlazado a datos, en lugar de utilizar los
Asistentes, escribe el código fuente necesario.

En el siguiente enlace te lo explico. Lo único que tienes que hacer es
cambiar los objetos del espacio de nombre OleDb, por los mismos objetos
correspondientes al espacio de nombres SqlClient:

Cómo crear un enlace de datos en tiempo de ejecución
http://mvp-access.com/softjaen/base...onet08.htm

¿Para que sirven las siguientes lineas, ya que si las quito
tambien funciona?, ¿Son necesarias?

Dim scb As New SqlCommandBuilder(sda)
sda.InsertCommand = scb.GetInsertCommand()
sda.UpdateCommand = scb.GetUpdateCommand()
sda.DeleteCommand = scb.GetDeleteCommand()



Esos comandos sirven para generar automáticamente los objetos Command
necesarios para insertar, actualizar y eliminar registros, y aunque los
elimines te funciona porque estás trabajando con una sola tabla, que
seguramente no estará relacionada con otra tabla mediante un diagrama.

Tambien me gustaria saber que debo ejecutar cuando cierre el formulario y
cerrar todos las conexiones abiertas, dataadapter, dataset, datatable,
...



Si el formulario que deseas cerrar, lo has abierto de manera «modal»,
puedes
llamar a su método «Dispose», si deseas que se destruya inmediatamente,
cosa
ésta que se hará automáticamente cuando cierres el formulario principal y
por tanto la aplicación.

En cuanto al cierre de conexiones, lo recomendado es que la tengas abierta
el tiempo suficiente para abrir o actualizar un origen de los datos, y
establezcas su valor a «Nothing» (al igual que los restantes objetos que
comentas), cuando no los vayas a utilizar más, para que de ésta manera, se
eliminen definitivamente del montón administrado, cuando se ejecute el
recolector de elementos no utilizados.

Un saludo

Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado
o
sugerido en el presente mensaje.







Respuesta Responder a este mensaje
#3 SoftJaén
10/08/2006 - 11:21 | Informe spam
"Francisco" escribió:

En el primer caso, efectivamente el campo ID es clave y no puede estar a
NULL, pero el problema es que se lo especifico en el textbox txtID que
esta
enlazado de la siguiente manera:

txtID.DataBindings.Add("Text", dtPrincipal, "ID")

pero no me tiene en cuenta el valor introducido y lo borrar de la caja de
texto.
En cambio en los otros campos parece que va bien.




De nunca he sido muy partidario de tener controles enlazados a datos, porque
dan más problemas que beneficios.

Ignoro el motivo para que se elimine el valor escrito en el control Textbox,
porque quiero reproducir el problema, y no soy capaz de conseguirlo. Obtengo
la excepción si introduzco un valor NULL o un valor duplicado, pero no se me
borran los datos. ¿?

Tambien he estado viendo el link que me dices y me surge una duda en el
metodo update.
Si rellenas el ds con la nueva consulta, ¿no se pierden las modificaciones
que habias realizado antes?



No me entero muy bien. ¿A qué modificaciones te refieres? ¿A las existentes
previamente en el objeto DataSet, antes de llamar al método «Fill» del
objeto DataAdapter? El método «Fill» rellena o actualiza un objeto DataSet.

El objeto DataSet de ADO .NET trabaja de una manera desconectada del origen
de datos, por lo que una vez creado un objeto DataTable, el objeto
DataAdapter automáticamente cierra la conexión para trabajar con el conjunto
de datos, pero las modificaciones afectan a los datos existentes en algún
objeto DataTable incluido en el objeto DataSet.


' Enviamos los cambios a la base de datos
da.Update(ds, tableName)

y cuando se envie los datos a la base de dato no enviara los ultimos
obtenido, ya que los modificados en el ds se han perdido??



Cuando se ejecuta el método «Update» del objeto DataAdapter, nuevamente se
abre la conexión para actualizar la base de datos únicamente con aquellos
registros que han sufrido alguna modificación en el objeto DataSet (o mejor
dicho, en algún objeto DataTable incluido en aquel), con respecto a los
datos existentes en la base de datos, por tanto, entiendo que el método
«Update» envía los datos tal y como se encuentran en el objeto DataSet en
ese momento preciso.

Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado
o sugerido en el presente mensaje.
Respuesta Responder a este mensaje
#4 Francisco
10/08/2006 - 12:28 | Informe spam
Hola Enrique:

De nunca he sido muy partidario de tener controles enlazados a datos,
porque
dan más problemas que beneficios.



Si no enlazas los controles a datos, entiendo que entonces te tienes tu que
encargar del traspasar los datos a los controles, y despues al aceptar el
registro, recorrerlos y actualizar todos los fields del registro para
grabarlo. Tambien debes realizar manualmente la carga de datos en los
controles cuando te desplazas por los registros. ¿Es asi? o exite alguna
forma mejor que desconozco.

No me entero muy bien. ¿A qué modificaciones te refieres? ¿A las
existentes
previamente en el objeto DataSet, antes de llamar al método «Fill» del
objeto DataAdapter? El método «Fill» rellena o actualiza un objeto
DataSet.



Segun entiendo, cuando en un formulario cambias los datos sobre los textbox
se cambian en el dataset, si realizas de nuevo el metodo fill sobre el
dataadapter creado de nuevo, ¿no se pierden las modificaciones que has
realizado sobre los textbox? o por el contrario hace una mezcla de los dos??

Perdona si las preguntas que te hago parezcan de principiante, pero es que
no llego a entender completamente como funciona el ADO.NET y .NET con
respecto a los datos, y los que quiero es determinar cual es la mejor
tecnica para enlazar un simple formulario, con sus controles y un origen de
datos, donde tenga la funcionalidad basica (Nuevo, Modificar, Aceptar,
Cancelar, Eliminar), mira que son muchos años programando, y he visto muchas
tecnologias, a lo largo que este tiempo, pero esto se me resiste, y estoy
convencido de que es falta de conceptos, he leido mucho sobre el tema pero
solo hablan de los metodos de una forma muy generica e incompleta.

En VB6 con ADO, basicamente de siempre he abierto una conexion, luego un
recordset con la tabla o consulta, he enlazado los controles al recordset y
cuando se modificaban, utilizaba el metodo update del recordset, cuando era
nuevo ejecutaba el metodo AddNew, y luego para actualizar de nuevo el metodo
update, para eliminar el metodo delete, y al finalizaz el formulario cerraba
recordset y conexion, despues se igualaba a Nothing para destruirlos, claro
todo esto bajo una clase que se encargaba de controlar todas las
excepciones.

Por eso no entiendo que para actualizar el origen de datos no baste solo con
llamar al metodo update.

De la manera que lo tengo hecho, a excepcion de alguna optimización, casi lo
tengo averiguado, lo que me sigue faltando es el dicho NULL en el ID cuando
en la caja de texto se le ha especificado un codigo. Supongo que no habra
que indicarselo a mano. Que como es un formulario base, no se como acceder a
ver los valores de los objetos en el formulario heredado.

Si sabes de un ejemplo con la gestion de un formulario basico de datos
completo, te agradeceria que me lo indicaras.

Gracias.
Saludos.
Respuesta Responder a este mensaje
#5 SoftJaén
10/08/2006 - 16:56 | Informe spam
"Francisco" escribió:

Si no enlazas los controles a datos, entiendo que entonces te tienes tu
que encargar del traspasar los datos a los controles, y despues al aceptar
el registro, recorrerlos y actualizar todos los fields del registro para
grabarlo. Tambien debes realizar manualmente la carga de datos en los
controles cuando te desplazas por los registros. ¿Es asi? o exite alguna
forma mejor que desconozco.



Si los controles no están enlazados a datos, te tienes que encargar de
escribir el código necesario para traspasar los datos a los controles, en el
supuesto de leer los datos existentes en la base de datos, es decir,
efectuar una consulta a la base de datos. Pero si lo que deseas hacer es
consultar, uno a uno, todos los registros existentes en una tabla, puedo
entender que enlaces los controles a datos por comodidad, dado que no tienes
que escribir código alguno, aunque pienso que para el usuario final de tu
aplicación, quizás no tenga demasiado sentido el tener que ir pulsando los
correspondientes botones para navegar por el conjunto de datos. Si deseas
presentarle al usuario varios registros a la misma vez, puede resultarte
útil un control DataGridView, por ejemplo.

Segun entiendo, cuando en un formulario cambias los datos sobre los
textbox se cambian en el dataset, si realizas de nuevo el metodo fill
sobre el dataadapter creado de nuevo, ¿no se pierden las modificaciones
que has realizado sobre los textbox? o por el contrario hace una mezcla de
los dos??



Si llamas de nuevo al método «Fill», antes de actualizar el origen de los
datos ejecutando el método «Update» del objeto DataAdapter, el DataSet se
limpia de datos y se rellenará de nuevo con los datos existentes en la base
de datos, por lo que obviamente, las modificaciones efectuadas se perderán.

Si deseas que no se pierdan las modificaciones, primeramente deberás
actualizar el origen de los datos (la tabla de la base de datos), y
posteriormente llamar al método «Fill».

Perdona si las preguntas que te hago parezcan de principiante, pero es que
no llego a entender completamente como funciona el ADO.NET y .NET con
respecto a los datos, y los que quiero es determinar cual es la mejor
tecnica para enlazar un simple formulario, con sus controles y un origen
de datos, donde tenga la funcionalidad basica (Nuevo, Modificar, Aceptar,
Cancelar, Eliminar), mira que son muchos años programando, y he visto
muchas tecnologias, a lo largo que este tiempo, pero esto se me resiste, y
estoy convencido de que es falta de conceptos, he leido mucho sobre el
tema pero solo hablan de los metodos de una forma muy generica e
incompleta.



Con ADO .NET existen dos formas de trabajar: conectado y desconectado del
origen de datos. El utilizar una forma u otra de trabajo, dependerá en gran
medida de la lógica de tu aplicación.

Para trabajar de una manera conectada, no hace falta que utilices objetos
DataAdapter, DataSet, DataTable, etc., dado que lo único que tienes que
hacer es abrir la conexión con el origen de los datos, leer los datos
mediante el correspondiente objeto DataReader, y ejecutar las consultas
T-SQL apropiadas para actualizar la base de datos. Si las consulta T-SQL son
de acción (UPDATE, DELETE, INSERT INTO), las ejecutarías utilizando el
método «ExecuteNonQuery» de un objeto SqlCommand (en el caso de trabajar con
bases de datos SQL Server). Es lo mismo que se hacía con la biblioteca de
ADO clásica, cuando deseábamos actualizar un origen de datos: utilizar el
método «Execute» de un objeto ADODB.Connection para ejecutar la consulta
T-SQL.

Y referente a trabajar con ADO .NET de una manera desconectada, viene a ser
parecido a cómo se trabajaba en ADO clásico con lo que se denominada
«Recordset desconectados», por lo que se tenía que abrir un objeto Recordset
del lado cliente, cuyo tipo de bloqueo fuera «adLockBatchOptimistic», y
enviar las actualiciones por lotes ejecutando el método «UpdateBatch» del
objeto Recordset.

Pero en ADO .NET el concepto de «conjunto de registros» (que era lo que
significaba un objeto Recordset), ha desaparecido para dar paso al concepto
de «conjunto de datos», que es en lo que se basa el objeto DataSet y
restantes objetos del espacio de nombres System.Data, por lo que tu puedes
tener un conjunto de datos, bien creado directamente, o rellenarlo
automáticamente con datos procedentes de una base de datos, en cuyo caso
necesitarás hace uso de un objeto DataAdapter, que viene a representar el
objeto que hace de puente entre el DataSet y el origen de los datos. De esta
forma, estás trabajando con un conjunto de datos, haciendo las oportunas
modificaciones en el mismo (insertar nuevos registros, actualizarlos,
eliminarlos), y cuando creas conveniente actualizar el origen de los datos,
llamas al método «Update» del objeto DataAdapter.

Lo bueno que tiene el objeto DataSet, es que puedes rellenarlo de datos
procedentes de una base de datos Microsoft Access, y enviarlos
posteriormente a una base de datos Microsoft SQL Server, o viceversa.

Los entendidos en el tema, dicen que el objeto DataSet puede ser idóneo para
aplicaciones cliente/servidor de Windows Forms, porque está claro que
solamente accedes al servidor de la red al cargar los datos y actualizar
posteriormente los mismos, por lo que el tráfico de red se ve disminuido al
trabajar desconectado del origen de datos.

En VB6 con ADO, basicamente de siempre he abierto una conexion, luego un
recordset con la tabla o consulta, he enlazado los controles al recordset
y cuando se modificaban, utilizaba el metodo update del recordset, cuando
era nuevo ejecutaba el metodo AddNew, y luego para actualizar de nuevo el
metodo update, para eliminar el metodo delete, y al finalizaz el
formulario cerraba recordset y conexion, despues se igualaba a Nothing
para destruirlos, claro todo esto bajo una clase que se encargaba de
controlar todas las excepciones.

Por eso no entiendo que para actualizar el origen de datos no baste solo
con llamar al metodo update.



Bueno, más o menos ya te he dado una idea de cómo trabajar con ADO .NET.
Prácticamente es parecido a trabajar con un Recordset de ADO clásico, con la
diferencia que se trabaja de una manera desconectada del origen de datos, de
ahí, que si deseas actualizar éstos últimos, necesariamente tendrás que
utilizar el método «Update» del objeto que hace de puente, el objeto
DataAdapter, porque como bien podrás comprender, tiene que haber algún
mecanismo para actualizar la base de datos.

De la manera que lo tengo hecho, a excepcion de alguna optimización, casi
lo tengo averiguado, lo que me sigue faltando es el dicho NULL en el ID
cuando en la caja de texto se le ha especificado un codigo. Supongo que no
habra que indicarselo a mano. Que como es un formulario base, no se como
acceder a ver los valores de los objetos en el formulario heredado.

Si sabes de un ejemplo con la gestion de un formulario basico de datos
completo, te agradeceria que me lo indicaras.



Se me ocurre que puedes declarar una clave principal al objeto DataTable
(dtPrincipal), para que de ésta forma puedas detectar las excepciones
producidas antes de actualizar el origen de datos.

Siguiendo con el ejemplo que te indiqué de mi página web, dentro de los
botones de navegación, puedes escribir un bloque Try ... End Try, para
atrapar las excepciones, y actuar en consecuencia:

Private Sub btnFirst_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnFirst.Click
Try
bmb.Position = 0
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try

End Sub

Private Sub btnPrevious_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnPrevious.Click
Try
bmb.Position -= 1
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try

End Sub

Private Sub btnNext_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnNext.Click
Try
bmb.Position += 1
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try

End Sub

Private Sub btnLast_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnLast.Click
Try
bmb.Position = bmb.Count - 1
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try

End Sub


Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente Respuesta Tengo una respuesta
Search Busqueda sugerida