Guardar datos con ADO.Net

29/08/2006 - 13:23 por Roberto | Informe spam
Hola a todos.

Tengo un problema al grabar los cambios de un DataSet en una base de datos
de Access 2000 con ADO.Net.

Para empezar el error es: UPDATE no puede encontrar TableMaping'Table' o
DataTable'Table'.

La ayuda general dice que para este error puede no generarse bien el
commandbuder si la SELECT que llena el DataAdapter tiene pocos datos o
INNERJOINs o las tablas no tienen clave principal. Más adelante vereis que
uso una SELECT * de lo más simple para llenar el DataAdapter, los nombres de
las tablas están bien y todas tienen clave principal.

Me hice una función a la que le paso por referencia el DataSet y el
DataAdapter, ya la he utilizado con otro DataSet y me funcionó perfectamente:

Public Function GuardarCambiosDS(ByRef ds As DataSet, ByRef da As
OleDbDataAdapter) As Boolean
Dim cb As New OleDbCommandBuilder(da)

'He probado a recuperar los comandos del CommandBuilder por lo que
dice la ayuda pero tampoco es esto.
da.UpdateCommand = cb.GetUpdateCommand
da.InsertCommand = cb.GetInsertCommand
da.DeleteCommand = cb.GetDeleteCommand

Try
da.Update(ds)
ds.AcceptChanges()
Return True
Catch ex As Exception
Return False
End Try
End Function

El Dataset lo relleno así:
Dim MiC As OleDbConnection
Dim MiDA As OleDbDataAdapter
Dim MiDS As DataSet
Dim dr As DataRow

MiC = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data
Source=" & FICHERO.MDB & "; Jet OLEDB:Database Password=" & pswBaseDeDatos &
";")

'Tiene cuatro tablas, he probado tanto poniendo las cuatro como con la que
voy a actualizar en este momento unicamente.
MiDA = New OleDbDataAdapter("SELECT * FROM Cabecera", MiC)
MiDA.Fill(MiDS, "Cabecera")
MiDA = New OleDbDataAdapter("SELECT * FROM Descripcion", MiC)
MiDA.Fill(MiDS, "Descripcion")
MiDA = New OleDbDataAdapter("SELECT * FROM Formas", MiC)
MiDA.Fill(MiDS, "Formas")
MiDA = New OleDbDataAdapter("SELECT * FROM Cancelaciones", MiC)
MiDA.Fill(MiDS, "Cancelaciones")

'Añado un nuevo registro:
dr = MiDS.Tables("Cabecera").NewRow
dr.Item("Numero") = Numero
MiDS.Tables("Cabecera").Rows.Add(dr)

'Llamo a la función para guardarlo.
If GuardarCambiosDS(MiDS, MiDA) Then
MiDA.Dispose()
MiC.Close()
End If

Preguntas similare

Leer las respuestas

#1 Roberto
29/08/2006 - 16:21 | Informe spam
De momento puedo guardar los datos desde un DataTable. He hecho una función
igual a la anterior pero pasándole un objeto DataTable en lugar del DataSet,
pero me vendría bien poder hacerlo con todo el DataSet completo para ir
rellenando las diferentes tablas a cada paso y guardarlas todas juntas al
confirmar al final del proceso.

"Roberto" wrote:

Hola a todos.

Tengo un problema al grabar los cambios de un DataSet en una base de datos
de Access 2000 con ADO.Net.

Para empezar el error es: UPDATE no puede encontrar TableMaping'Table' o
DataTable'Table'.

La ayuda general dice que para este error puede no generarse bien el
commandbuder si la SELECT que llena el DataAdapter tiene pocos datos o
INNERJOINs o las tablas no tienen clave principal. Más adelante vereis que
uso una SELECT * de lo más simple para llenar el DataAdapter, los nombres de
las tablas están bien y todas tienen clave principal.

Me hice una función a la que le paso por referencia el DataSet y el
DataAdapter, ya la he utilizado con otro DataSet y me funcionó perfectamente:

Public Function GuardarCambiosDS(ByRef ds As DataSet, ByRef da As
OleDbDataAdapter) As Boolean
Dim cb As New OleDbCommandBuilder(da)

'He probado a recuperar los comandos del CommandBuilder por lo que
dice la ayuda pero tampoco es esto.
da.UpdateCommand = cb.GetUpdateCommand
da.InsertCommand = cb.GetInsertCommand
da.DeleteCommand = cb.GetDeleteCommand

Try
da.Update(ds)
ds.AcceptChanges()
Return True
Catch ex As Exception
Return False
End Try
End Function

El Dataset lo relleno así:
Dim MiC As OleDbConnection
Dim MiDA As OleDbDataAdapter
Dim MiDS As DataSet
Dim dr As DataRow

MiC = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data
Source=" & FICHERO.MDB & "; Jet OLEDB:Database Password=" & pswBaseDeDatos &
";")

'Tiene cuatro tablas, he probado tanto poniendo las cuatro como con la que
voy a actualizar en este momento unicamente.
MiDA = New OleDbDataAdapter("SELECT * FROM Cabecera", MiC)
MiDA.Fill(MiDS, "Cabecera")
MiDA = New OleDbDataAdapter("SELECT * FROM Descripcion", MiC)
MiDA.Fill(MiDS, "Descripcion")
MiDA = New OleDbDataAdapter("SELECT * FROM Formas", MiC)
MiDA.Fill(MiDS, "Formas")
MiDA = New OleDbDataAdapter("SELECT * FROM Cancelaciones", MiC)
MiDA.Fill(MiDS, "Cancelaciones")

'Añado un nuevo registro:
dr = MiDS.Tables("Cabecera").NewRow
dr.Item("Numero") = Numero
MiDS.Tables("Cabecera").Rows.Add(dr)

'Llamo a la función para guardarlo.
If GuardarCambiosDS(MiDS, MiDA) Then
MiDA.Dispose()
MiC.Close()
End If
Respuesta Responder a este mensaje
#2 Jesús López
29/08/2006 - 18:53 | Informe spam
Para evitar el error "UPDATE no puede encontrar TableMaping'Table' o
DataTable'Table" debes añadir a la colección TableMappings del DataAdapter
el TableMaping predeterminado cuyo nombre es "Table". Por ejemplo:

Dim daCabecera As New OleDbDataAdapter("SELECT * FROM Cabecera", cn )
daCabecera.TableMappings.Add("Table", "Cabecera")
daCabecera.Fill(ds)


Dim daDescripcion As New OleDbDataAdapter("SELECT * FROM Descripcion", cn)
daDescripcion.TableMappings.Add("Table", "Descripcion")
daDescripcion.Fill(ds)

' Aquí escribimos código que modifica las datatables Cabecera y Descripcion"

Ahora si llamas a:

GuardarCambios(ds, daCabecera)
GuardarCambios(ds, daDescripcion)

Funcionará a la perfección.

Observa que en los métodos Fill de los adapters no incluyo el nombre del
datatable, a pesar de ello habrá en el dataset un datatable Cabecera y otro
Descripcion. El TableMapping preterminado hace innecesario especificar el
nombre del datatable en el método Fill.

El método update es similar al método Fill en lo que al datatable afectado
se refiere. Es decir, se puede especificar el datatable sobre el que actuar
mediante su nombre o mediante el TableMapping predeterminado. Pero de alguna
manera el adapter necesita saber sobre qué datatable debe actuar y si no se
le proporciona esa información el adapter se quejará lanzando una excepción.


Saludos:

Jesús López


"Roberto" escribió en el mensaje
news:
Hola a todos.

Tengo un problema al grabar los cambios de un DataSet en una base de datos
de Access 2000 con ADO.Net.

Para empezar el error es: UPDATE no puede encontrar TableMaping'Table' o
DataTable'Table'.

La ayuda general dice que para este error puede no generarse bien el
commandbuder si la SELECT que llena el DataAdapter tiene pocos datos o
INNERJOINs o las tablas no tienen clave principal. Más adelante vereis que
uso una SELECT * de lo más simple para llenar el DataAdapter, los nombres
de
las tablas están bien y todas tienen clave principal.

Me hice una función a la que le paso por referencia el DataSet y el
DataAdapter, ya la he utilizado con otro DataSet y me funcionó
perfectamente:

Public Function GuardarCambiosDS(ByRef ds As DataSet, ByRef da As
OleDbDataAdapter) As Boolean
Dim cb As New OleDbCommandBuilder(da)

'He probado a recuperar los comandos del CommandBuilder por lo que
dice la ayuda pero tampoco es esto.
da.UpdateCommand = cb.GetUpdateCommand
da.InsertCommand = cb.GetInsertCommand
da.DeleteCommand = cb.GetDeleteCommand

Try
da.Update(ds)
ds.AcceptChanges()
Return True
Catch ex As Exception
Return False
End Try
End Function

El Dataset lo relleno así:
Dim MiC As OleDbConnection
Dim MiDA As OleDbDataAdapter
Dim MiDS As DataSet
Dim dr As DataRow

MiC = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data
Source=" & FICHERO.MDB & "; Jet OLEDB:Database Password=" & pswBaseDeDatos
&
";")

'Tiene cuatro tablas, he probado tanto poniendo las cuatro como con la que
voy a actualizar en este momento unicamente.
MiDA = New OleDbDataAdapter("SELECT * FROM Cabecera", MiC)
MiDA.Fill(MiDS, "Cabecera")
MiDA = New OleDbDataAdapter("SELECT * FROM Descripcion", MiC)
MiDA.Fill(MiDS, "Descripcion")
MiDA = New OleDbDataAdapter("SELECT * FROM Formas", MiC)
MiDA.Fill(MiDS, "Formas")
MiDA = New OleDbDataAdapter("SELECT * FROM Cancelaciones", MiC)
MiDA.Fill(MiDS, "Cancelaciones")

'Añado un nuevo registro:
dr = MiDS.Tables("Cabecera").NewRow
dr.Item("Numero") = Numero
MiDS.Tables("Cabecera").Rows.Add(dr)

'Llamo a la función para guardarlo.
If GuardarCambiosDS(MiDS, MiDA) Then
MiDA.Dispose()
MiC.Close()
End If
Respuesta Responder a este mensaje
#3 Jesús López
29/08/2006 - 20:12 | Informe spam
A parte de lo relacionado con los TableMappings me gustaría hacerte un par
de sugerencias.

En primer lugar me llama la atención que el método GuardarCambios reciba por
referencia tanto el dataset como el adapter. Esto no es necesario y supone
un coste adicional de proceso por la doble indirección que requiere. Los
datasets y adapters son clases y por tanto tipo referencia, así que si los
pasas por valor no se hace una copia de los objetos al pasarlos al método
sino que simplemente se pasa una referencia al objeto. En definitiva, yo
usaría paso por valor en vez de por referencia.

Por otra parte, en la programación en C clásica el tratamiento de errores se
basa en que las funciones devuelvan un valor que indica si la función tuvo
éxito o no. Esta forma de tratar los errores ha sido históricamente una
fuente de problemas. Básicamente por dos razones: primera, el código es
difícil de seguir al estar mezclado la lógica con el tratamiento de errores,
es difícil diferenciar que es lógica y qué es tratamiento de errores.
Segunda, los errores resultan fáciles de ignorar, un programador puede
olvidar comprobar el valor devuelto por una función, así resultan programas
que cuando fallan no informan al usuario del fallo, o librerías que cuando
fallan nadie se entera. Para solucionar estos problemas los lenguajes de
programación modernos como Visual Basic incluyen el "tratamiento
estructurado de excepciones" en el que si un método encuentra una condición
de error, lanza una excepción, en vez de devolver un código de error. Todo
este rollo viene porque tu método GuardarCambios devuelve un valor boolean
que indica si ha tenido éxito o no, lo que concuerda con el patrón de la
forma clásica de tratamiento de errores. Con el "tratamiento estructurado de
excepciones" GuardarCambios debería lanzar una excepción si falla.

Por último la llamada a AcceptChanges es complétamente innecesaria, peor
aún, puede dar lugar a comportamientos incorrectos. Es innecesaria porque el
método Update del adapter ya llama a AcceptChanges y puede dar lugar a
comportamientos incorrectos porque estás llamando a AcceptChanges sobre el
dataset completo cuando hay otras datatables en el dataset que pueden
contener cambios.

Saludos:

Jesús López





"Roberto" escribió en el mensaje
news:
Hola a todos.

Tengo un problema al grabar los cambios de un DataSet en una base de datos
de Access 2000 con ADO.Net.

Para empezar el error es: UPDATE no puede encontrar TableMaping'Table' o
DataTable'Table'.

La ayuda general dice que para este error puede no generarse bien el
commandbuder si la SELECT que llena el DataAdapter tiene pocos datos o
INNERJOINs o las tablas no tienen clave principal. Más adelante vereis que
uso una SELECT * de lo más simple para llenar el DataAdapter, los nombres
de
las tablas están bien y todas tienen clave principal.

Me hice una función a la que le paso por referencia el DataSet y el
DataAdapter, ya la he utilizado con otro DataSet y me funcionó
perfectamente:

Public Function GuardarCambiosDS(ByRef ds As DataSet, ByRef da As
OleDbDataAdapter) As Boolean
Dim cb As New OleDbCommandBuilder(da)

'He probado a recuperar los comandos del CommandBuilder por lo que
dice la ayuda pero tampoco es esto.
da.UpdateCommand = cb.GetUpdateCommand
da.InsertCommand = cb.GetInsertCommand
da.DeleteCommand = cb.GetDeleteCommand

Try
da.Update(ds)
ds.AcceptChanges()
Return True
Catch ex As Exception
Return False
End Try
End Function

El Dataset lo relleno así:
Dim MiC As OleDbConnection
Dim MiDA As OleDbDataAdapter
Dim MiDS As DataSet
Dim dr As DataRow

MiC = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data
Source=" & FICHERO.MDB & "; Jet OLEDB:Database Password=" & pswBaseDeDatos
&
";")

'Tiene cuatro tablas, he probado tanto poniendo las cuatro como con la que
voy a actualizar en este momento unicamente.
MiDA = New OleDbDataAdapter("SELECT * FROM Cabecera", MiC)
MiDA.Fill(MiDS, "Cabecera")
MiDA = New OleDbDataAdapter("SELECT * FROM Descripcion", MiC)
MiDA.Fill(MiDS, "Descripcion")
MiDA = New OleDbDataAdapter("SELECT * FROM Formas", MiC)
MiDA.Fill(MiDS, "Formas")
MiDA = New OleDbDataAdapter("SELECT * FROM Cancelaciones", MiC)
MiDA.Fill(MiDS, "Cancelaciones")

'Añado un nuevo registro:
dr = MiDS.Tables("Cabecera").NewRow
dr.Item("Numero") = Numero
MiDS.Tables("Cabecera").Rows.Add(dr)

'Llamo a la función para guardarlo.
If GuardarCambiosDS(MiDS, MiDA) Then
MiDA.Dispose()
MiC.Close()
End If
Respuesta Responder a este mensaje
#4 Roberto
30/08/2006 - 09:38 | Informe spam
Muchísimas gracias Jesús.

Precisamente pasaba los datasets y dataadapters como referencia porque no
quería que se creasen copias que consumiesen recursos innecesariamente. Los
cambiaré a por valor porque resulta que estaba consumiendo más recursos al
intentar juso lo contrario, gracias por el apunte.

La llamada al AceptChanges en este caso la quería hacer al final para todas
la tablas a la vez por si hubiese, por ejemplo, un error al guardar la última
poder hacer un rollback y tener todas las tablas sin 'aceptar' para repetir
el proceso si fuese necesario. Pensaba que la propiedad
AceptChangesDuringUpdate por defecto estaba deshabilitada, me lo miraré bien
a ver como me conviene más hacerlo.

Al tratamiento de errores es verdad que me está costando adaptarme pero ya
le voy cogiendo el aire, pasito a pasito.

"Roberto" wrote:

Hola a todos.

Tengo un problema al grabar los cambios de un DataSet en una base de datos
de Access 2000 con ADO.Net.

Para empezar el error es: UPDATE no puede encontrar TableMaping'Table' o
DataTable'Table'.

La ayuda general dice que para este error puede no generarse bien el
commandbuder si la SELECT que llena el DataAdapter tiene pocos datos o
INNERJOINs o las tablas no tienen clave principal. Más adelante vereis que
uso una SELECT * de lo más simple para llenar el DataAdapter, los nombres de
las tablas están bien y todas tienen clave principal.

Me hice una función a la que le paso por referencia el DataSet y el
DataAdapter, ya la he utilizado con otro DataSet y me funcionó perfectamente:

Public Function GuardarCambiosDS(ByRef ds As DataSet, ByRef da As
OleDbDataAdapter) As Boolean
Dim cb As New OleDbCommandBuilder(da)

'He probado a recuperar los comandos del CommandBuilder por lo que
dice la ayuda pero tampoco es esto.
da.UpdateCommand = cb.GetUpdateCommand
da.InsertCommand = cb.GetInsertCommand
da.DeleteCommand = cb.GetDeleteCommand

Try
da.Update(ds)
ds.AcceptChanges()
Return True
Catch ex As Exception
Return False
End Try
End Function

El Dataset lo relleno así:
Dim MiC As OleDbConnection
Dim MiDA As OleDbDataAdapter
Dim MiDS As DataSet
Dim dr As DataRow

MiC = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data
Source=" & FICHERO.MDB & "; Jet OLEDB:Database Password=" & pswBaseDeDatos &
";")

'Tiene cuatro tablas, he probado tanto poniendo las cuatro como con la que
voy a actualizar en este momento unicamente.
MiDA = New OleDbDataAdapter("SELECT * FROM Cabecera", MiC)
MiDA.Fill(MiDS, "Cabecera")
MiDA = New OleDbDataAdapter("SELECT * FROM Descripcion", MiC)
MiDA.Fill(MiDS, "Descripcion")
MiDA = New OleDbDataAdapter("SELECT * FROM Formas", MiC)
MiDA.Fill(MiDS, "Formas")
MiDA = New OleDbDataAdapter("SELECT * FROM Cancelaciones", MiC)
MiDA.Fill(MiDS, "Cancelaciones")

'Añado un nuevo registro:
dr = MiDS.Tables("Cabecera").NewRow
dr.Item("Numero") = Numero
MiDS.Tables("Cabecera").Rows.Add(dr)

'Llamo a la función para guardarlo.
If GuardarCambiosDS(MiDS, MiDA) Then
MiDA.Dispose()
MiC.Close()
End If
Respuesta Responder a este mensaje
#5 Roberto
30/08/2006 - 11:35 | Informe spam
Ahora que estaba revisando el código me he dado cuenta de que hacía algo mal,
estaba reutilizando el mismo DataAdapter para leer cada una de las tablas.
Esto para leerlas no me daba ningún problema, pero a la hora de grabar el
DataAdapter sólo conocía la última de las tablas.

Al releer tu post me he fijado en que usas dos DataAdapters diferentes y
realmente los cambios se guardan tabla por tabla. Nuevo error mio al hacer el
AceptChanges de todo el DataSet que me guardaría sólo una tabla y aceptaría
los cambios de todas las demás sin grabarlos.

"Jesús López" wrote:

Para evitar el error "UPDATE no puede encontrar TableMaping'Table' o
DataTable'Table" debes añadir a la colección TableMappings del DataAdapter
el TableMaping predeterminado cuyo nombre es "Table". Por ejemplo:

Dim daCabecera As New OleDbDataAdapter("SELECT * FROM Cabecera", cn )
daCabecera.TableMappings.Add("Table", "Cabecera")
daCabecera.Fill(ds)


Dim daDescripcion As New OleDbDataAdapter("SELECT * FROM Descripcion", cn)
daDescripcion.TableMappings.Add("Table", "Descripcion")
daDescripcion.Fill(ds)

' Aquí escribimos código que modifica las datatables Cabecera y Descripcion"

Ahora si llamas a:

GuardarCambios(ds, daCabecera)
GuardarCambios(ds, daDescripcion)

Funcionará a la perfección.

Observa que en los métodos Fill de los adapters no incluyo el nombre del
datatable, a pesar de ello habrá en el dataset un datatable Cabecera y otro
Descripcion. El TableMapping preterminado hace innecesario especificar el
nombre del datatable en el método Fill.

El método update es similar al método Fill en lo que al datatable afectado
se refiere. Es decir, se puede especificar el datatable sobre el que actuar
mediante su nombre o mediante el TableMapping predeterminado. Pero de alguna
manera el adapter necesita saber sobre qué datatable debe actuar y si no se
le proporciona esa información el adapter se quejará lanzando una excepción.


Saludos:

Jesús López


"Roberto" escribió en el mensaje
news:
> Hola a todos.
>
> Tengo un problema al grabar los cambios de un DataSet en una base de datos
> de Access 2000 con ADO.Net.
>
> Para empezar el error es: UPDATE no puede encontrar TableMaping'Table' o
> DataTable'Table'.
>
> La ayuda general dice que para este error puede no generarse bien el
> commandbuder si la SELECT que llena el DataAdapter tiene pocos datos o
> INNERJOINs o las tablas no tienen clave principal. Más adelante vereis que
> uso una SELECT * de lo más simple para llenar el DataAdapter, los nombres
> de
> las tablas están bien y todas tienen clave principal.
>
> Me hice una función a la que le paso por referencia el DataSet y el
> DataAdapter, ya la he utilizado con otro DataSet y me funcionó
> perfectamente:
>
> Public Function GuardarCambiosDS(ByRef ds As DataSet, ByRef da As
> OleDbDataAdapter) As Boolean
> Dim cb As New OleDbCommandBuilder(da)
>
> 'He probado a recuperar los comandos del CommandBuilder por lo que
> dice la ayuda pero tampoco es esto.
> da.UpdateCommand = cb.GetUpdateCommand
> da.InsertCommand = cb.GetInsertCommand
> da.DeleteCommand = cb.GetDeleteCommand
>
> Try
> da.Update(ds)
> ds.AcceptChanges()
> Return True
> Catch ex As Exception
> Return False
> End Try
> End Function
>
> El Dataset lo relleno así:
> Dim MiC As OleDbConnection
> Dim MiDA As OleDbDataAdapter
> Dim MiDS As DataSet
> Dim dr As DataRow
>
> MiC = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data
> Source=" & FICHERO.MDB & "; Jet OLEDB:Database Password=" & pswBaseDeDatos
> &
> ";")
>
> 'Tiene cuatro tablas, he probado tanto poniendo las cuatro como con la que
> voy a actualizar en este momento unicamente.
> MiDA = New OleDbDataAdapter("SELECT * FROM Cabecera", MiC)
> MiDA.Fill(MiDS, "Cabecera")
> MiDA = New OleDbDataAdapter("SELECT * FROM Descripcion", MiC)
> MiDA.Fill(MiDS, "Descripcion")
> MiDA = New OleDbDataAdapter("SELECT * FROM Formas", MiC)
> MiDA.Fill(MiDS, "Formas")
> MiDA = New OleDbDataAdapter("SELECT * FROM Cancelaciones", MiC)
> MiDA.Fill(MiDS, "Cancelaciones")
>
> 'Añado un nuevo registro:
> dr = MiDS.Tables("Cabecera").NewRow
> dr.Item("Numero") = Numero
> MiDS.Tables("Cabecera").Rows.Add(dr)
>
> 'Llamo a la función para guardarlo.
> If GuardarCambiosDS(MiDS, MiDA) Then
> MiDA.Dispose()
> MiC.Close()
> End If



email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida