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

#6 SoftJaén
10/08/2006 - 17:06 | Informe spam
Bueno, se me ha olvidado indicarte cómo crear la clave principal del objeto
DataTable. En el evento Load del formulario, inserta lo siguiente:

Dim column As New DataColumn
column.ColumnName = "ID"

' Añado la columna al array.
Dim keys(0) As DataColumn
keys(0) = dtPrincipal.Columns(0)

' Establezco la clave principal de la tabla
dtPrincipal.PrimaryKey = keys

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
#7 Francisco
11/08/2006 - 08:43 | Informe spam
Hola Enrique.

En principio muchas gracias por tu ayuda ya que ha hecho que tenga mas claro
el tema.

Efectivamente el acceso de datos desconectado es lo mas adecuado y lo mas
optimo aunque tengamos la perdida de rendimiento en las conexiones. Yo
trabajaba con el tipo de bloqueo «adLockBatchOptimistic» en los formularios
maestros.

Probare lo de crear la columna como clave para ver si puedo interceptar la
excepcion antes.

En cuanto al tema de actualizar el origen de datos en tu pagina Web pones el
siguiente codigo:

Private Sub UpdateOleDb(ByVal ds As DataSet, _
ByVal cnnString As String, _
ByVal SQL As String, _
ByVal tableName As String)

' Creamos un objeto OleDbConnection
Dim cnn As New OleDbConnection(cnnString)

Try
' Abrimos la conexión
cnn.Open()

' Creamos un adaptador de datos
Dim da As New OleDbDataAdapter(SQL, cnn)

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

' Creo un objeto CommandBuilder para actualizar los datos
Dim cmdBuilder As New OleDbCommandBuilder(da)
With da
.InsertCommand = cmdBuilder.GetInsertCommand
.DeleteCommand = cmdBuilder.GetDeleteCommand
.UpdateCommand = cmdBuilder.GetUpdateCommand
End With

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

Catch ex As Exception
MessageBox.Show(ex.Message, "Actualizar Datos")

Finally
' Cerramos la conexión
cnn.Close()
End Try

End Sub

Mi duda sigue siendo la misma, si tienes un dataset con modificaciones
realizadas que se lo pasa como parametro, y antes de realizar el update
llamas de nuevo al metodo fill, despues de abrir la conexion y crear el
dataadapter, ¿No se pierden las modificaciones realizadas en el ds?

Muchas Gracias
Saludos.
Respuesta Responder a este mensaje
#8 SoftJaén
11/08/2006 - 15:21 | Informe spam
"Francisco" escribió:


En cuanto al tema de actualizar el origen de datos en tu pagina Web pones
el siguiente codigo:

Private Sub UpdateOleDb(ByVal ds As DataSet, _
ByVal cnnString As String, _
ByVal SQL As String, _
ByVal tableName As String)

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


End Sub

Mi duda sigue siendo la misma, si tienes un dataset con modificaciones
realizadas que se lo pasa como parametro, y antes de realizar el update
llamas de nuevo al metodo fill, despues de abrir la conexion y crear el
dataadapter, ¿No se pierden las modificaciones realizadas en el ds?



Tal y como tengo escrito el procedimiento «UpdateOleDb», no se pierde
ninguna modificación. Es más, puedes llamar al procedimeinto cada vez que
desees enviar las actualizaciones a la base de datos. Mientras que no llames
a la función «CreateDataSetOleDb» una segunda vez (cosa que en el ejemplo
sólo se hace una única vez, dentro del evento Load), los datos existentes en
el objeto DataSet son los mismos, con las modificaciones que se hayan podido
efectuar con posterioridad a su creación.

Ahora bien, como el objeto DataSet tiene una visibilidad a nivel de la
propia clase Form, si llamas a la función «CreateDataSetOleDb», antes de
llamar al método «UpdateOleDb», se eliminarán todos los datos existentes en
el DataSet, y éste se rellenará de nuevo con los datos existentes
actualmente en la base de datos.

Puedes pensar en el objeto DataSet como si fuera una pequeña base de datos
residente en memoria, con sus correspondientes tablas (los objetos
DataTable), por lo que mientras que no crees de nuevo el mismo objeto
DataSet (dsPrincipal), éste contendrá los datos cargados en un primer
momento, junto con las modificaciones efectuadas posteriormente. Al método
«UpdateOleDb» únicamente hay que llamarlo cuando deseas actualizar la base
de datos, porque el objeto DataSet, al estar trabajando con controles
enlazados a datos, se actualiza sólo, cada vez que cambies de registro.

Si te fijas bien en el procedimiento «UpdateOleDb», dentro del mismo es
donde construyo el objeto DataAdapter (que como te indiqué, es el objeto que
hace de puente entre el DataSet y la base de datos), por tanto estoy
trabajando con un objeto DataAdapter a nivel del propio procedimiento, es
decir, a nivel local, por lo que se destruirá una vez que el código abandone
el procedimiento, o mejor dicho, y ya que estamos trabajando con .net,
desaparecerá del montón administrado cuando se produzca una recolección de
elementos no utilizados, pero si tiene un valor Nothing, o ha salido fuera
de su ámbito de visibilidad, el objeto DataAdapter no tiene ninguna validez,
aunque la recolección de elementos no utilizados tarde 24 horas en
producirse. :-)

Como necesariamente hay que utilizar un objeto DataAdapter para enviar las
actualizaciones al origen de datos, es por lo que tengo que llamar al método
«Fill», el cual sirve tanto para RELLENAR un conjunto de datos, como para
ACTUALIZAR el origen de aquellos (la base de datos), de tal forma que
coincidan con las filas del origen de datos utilizando los nombres de los
objetos DataSet y DataTable.

Si el objeto DataAdapter tuviera otro ámbito de visibilidad, por ejemplo
estuviera declarado a nivel del módulo de la propia clase Form, que es como
tú lo tienes declarado, "otro gallo cantaría", porque entonces no haría
falta llamar al método «Fill» en el procedimiento «UpdateOleDb»; con llamar
al método «Update» del propio objeto DataAdapter, sería suficiente, siempre
y cuando hayamos especificado las propiedades correspondientes del objeto
CommandBuilder.

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
#9 Francisco Garzon
11/08/2006 - 19:21 | Informe spam
Ok. lo probare y ya te cuento.

Saludos.

"SoftJaén" escribió en el mensaje
news:#
"Francisco" escribió:

>
> En cuanto al tema de actualizar el origen de datos en tu pagina Web


pones
> el siguiente codigo:
>
> Private Sub UpdateOleDb(ByVal ds As DataSet, _
> ByVal cnnString As String, _
> ByVal SQL As String, _
> ByVal tableName As String)
>
> ' Rellenamos el objeto DataSet con los datos
> ' de la consulta SQL
> da.Fill(ds, tableName)
>
>
> End Sub
>
> Mi duda sigue siendo la misma, si tienes un dataset con modificaciones
> realizadas que se lo pasa como parametro, y antes de realizar el update
> llamas de nuevo al metodo fill, despues de abrir la conexion y crear el
> dataadapter, ¿No se pierden las modificaciones realizadas en el ds?

Tal y como tengo escrito el procedimiento «UpdateOleDb», no se pierde
ninguna modificación. Es más, puedes llamar al procedimeinto cada vez que
desees enviar las actualizaciones a la base de datos. Mientras que no


llames
a la función «CreateDataSetOleDb» una segunda vez (cosa que en el ejemplo
sólo se hace una única vez, dentro del evento Load), los datos existentes


en
el objeto DataSet son los mismos, con las modificaciones que se hayan


podido
efectuar con posterioridad a su creación.

Ahora bien, como el objeto DataSet tiene una visibilidad a nivel de la
propia clase Form, si llamas a la función «CreateDataSetOleDb», antes de
llamar al método «UpdateOleDb», se eliminarán todos los datos existentes


en
el DataSet, y éste se rellenará de nuevo con los datos existentes
actualmente en la base de datos.

Puedes pensar en el objeto DataSet como si fuera una pequeña base de datos
residente en memoria, con sus correspondientes tablas (los objetos
DataTable), por lo que mientras que no crees de nuevo el mismo objeto
DataSet (dsPrincipal), éste contendrá los datos cargados en un primer
momento, junto con las modificaciones efectuadas posteriormente. Al método
«UpdateOleDb» únicamente hay que llamarlo cuando deseas actualizar la base
de datos, porque el objeto DataSet, al estar trabajando con controles
enlazados a datos, se actualiza sólo, cada vez que cambies de registro.

Si te fijas bien en el procedimiento «UpdateOleDb», dentro del mismo es
donde construyo el objeto DataAdapter (que como te indiqué, es el objeto


que
hace de puente entre el DataSet y la base de datos), por tanto estoy
trabajando con un objeto DataAdapter a nivel del propio procedimiento, es
decir, a nivel local, por lo que se destruirá una vez que el código


abandone
el procedimiento, o mejor dicho, y ya que estamos trabajando con .net,
desaparecerá del montón administrado cuando se produzca una recolección de
elementos no utilizados, pero si tiene un valor Nothing, o ha salido fuera
de su ámbito de visibilidad, el objeto DataAdapter no tiene ninguna


validez,
aunque la recolección de elementos no utilizados tarde 24 horas en
producirse. :-)

Como necesariamente hay que utilizar un objeto DataAdapter para enviar las
actualizaciones al origen de datos, es por lo que tengo que llamar al


método
«Fill», el cual sirve tanto para RELLENAR un conjunto de datos, como para
ACTUALIZAR el origen de aquellos (la base de datos), de tal forma que
coincidan con las filas del origen de datos utilizando los nombres de los
objetos DataSet y DataTable.

Si el objeto DataAdapter tuviera otro ámbito de visibilidad, por ejemplo
estuviera declarado a nivel del módulo de la propia clase Form, que es


como
tú lo tienes declarado, "otro gallo cantaría", porque entonces no haría
falta llamar al método «Fill» en el procedimiento «UpdateOleDb»; con


llamar
al método «Update» del propio objeto DataAdapter, sería suficiente,


siempre
y cuando hayamos especificado las propiedades correspondientes del objeto
CommandBuilder.

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
#10 Francisco
17/08/2006 - 11:49 | Informe spam
Hola Enrique:

Ya he averiguado donde estaba el problema, aunque todavia no lo he
solucionado.

El problema parece que esta en que no funciona bien la herencia en este
caso.
El formulario que tenia era de clientes, y estaba heredado desde un
formulario base, donde realizo las operaciones con BindingContext. Se ve que
para desplazarse por los registros funciona bien, pero no tanto cuando creas
un nuevo registro e intentas actualizarlo.

¿Es diferente el bindingcontext del formulario padre y del hijo?, ¿como debo
referenciar cada uno?

He probado ha hacer el formulario igual pero en un solo formulario sin
herencia y funciona bien, o por lo menos como debe de funcionar.

El problema esta solo en campos que son claves principales, ya que si le
indicaba que era autonumerico entonces va bien, pero no era lo que yo
necesitaba. Necesito permitir que el usuario indique el codigo que desee.

Me surge una pregunta: Cuando se define un dataSet y se rellena con una
tabla, este no coge que campos son clave.
Entonces cuando acepto un registro, y despues de lanzar el metodo update del
dataset, si la clave esta duplicada, salta el mensaje de infraccion de
primarykey, el registro no se graba en la base de datos, pero la fila si se
queda en el DataSet. ¿Que codigo debo de poner que compruebe que es nuevo y
que al dar el error eliminar esa fila devolviendo la posicion a la ultima
correcta?

Muchas Gracias
Saludos.
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida