DATASET Y DATAADAPTER.UPDATE

13/09/2005 - 14:35 por Alamo | Informe spam
Hola a todos.

Bueno creo que por el título ya se imaginan lo que voy a preguntar.

Espero que me puedan ayudar.

Supongamos que una hermanita de la caridad nos envía un dataset con un
conjunto de datos (dos tablas por ejemplo).

Bien, nosotros como chicos buenos, mostramos la información del dataset al
usuario mediante un grid o controles normales, y además como buenos
programadores le damos la oportunidad al usuario de modificar, añadir y
borrar información de los datos almacenados en el famoso dataset.

Hasta ahí todo va bien, el problema surge cuando queremos actualizar la
información que ha generado,modificado o eliminado el usuario en el dataset
con el Origen de Datos.

He leído y releído el msdn, documentación, foros, etc pero sigo sin
resolver mi problema.

Bueno el asunto:

Yo tengo una función la cual devuelve un dataset a través de un parámetro
con una consulta sql del tipo select, es decir: Le paso una sentencia sql y
un nombre de tabla, y esta me genera un dataset con dicha consulta y nombre
de tabla:

Public Function Crear_Conjunto_Datos(ByVal sql As String, ByVal nombre As
String) As System.Data.DataSet

A su vez tengo otra función la cual mediante un dataset pasado por
parametros, y una consulta sql, añado dicha consulta sql al dataset:

Public Function Anadir_Actualizar_Conjunto_Datos(ByVal sql As String, ByVal
nombre As String, ByRef conjunto As System.Data.DataSet, ByVal modo As
String) As Boolean

Hasta ahí todo perfecto, según mi proyecto, tendré tras llamar a estas dos
funciones, un dataset con dos tablas.

Ahora quiero actualizar los datos que se encuentran en el dataset modificado
por el usuario con el Origen de Datos.

Para ello me he creado una nueva función a la cual le paso por parámetros un
dataset por referencia (byref), y las distintas consultas sql que contiene
en su interior, es decir para mi proyecto tengo dos tablas las cuales se
corresponden a dos consultas sql.

Public Function Actualizar_Conjunto_Datos_Data_Set(ByRef conjunto As
System.Data.DataSet, ByVal sql_array() As String) As Boolean

Bueno que yo sepa para realizar la actualización del dataset con el origen
de datos, tengo que utilizar un objeto dataadapter al cual, para cada tabla
del dataset pasado por parametros, inicializo con el objeto conexion y con
la consulta sql correspondiente que necesita.

m_Adaptador = New OleDbDataAdapter(sql_array(i), c_conexion)


AHORA LA PREGUNTA: Toda la documentación dice que genere un objeto
comanndbuilder para que genere de forma automática los comandos
insert,delete y update necesarios para realizar la actualización. Pues si lo
hago tal y como dice la documentación:

"cmdComando = New OleDBCommandBuilder(m_Adaptador)"

cuando me dispongo a realizar la actualización de una tabla la cual haya
sido modificada con la instrucción:

"m_Adaptador.update(DataSet,"Tabla1")"

me sale el siguiente mensaje de error: "LA GENERACION SQL DINAMICA PARA
UPDATECOMMAND NO ES COMPATIBLE CON SELECTCOMMAND, QUE NO DEVUELVE NINGUNA
INFORMACIÓN SOBRE COLUMNAS CLAVE"

Bueno yo creo que ese mensaje de error es por que no se ha inicializado el
objeto UpdateCommand del adaptador de datos. Según la documentación solo con
la instrucción anteriormente mencionada: "cmdComando = New
OleDBCommandBuilder(m_Adaptador)" el entorno de forma automática genera los
comandos pero no es así.

Añado las siguientes instrucciones:

"m_adaptador.selectcommand = new oledebcommand(sql,conexion)
m_adaptador.insertcommand = new oledbcommand(sql,conexion)
m_adaptador.deletecommand = new oledbcommand(sql,conexion)
m_adaptador.updatecommand = new oledbcommand(sql,conexion)"

la sentencia sql es la misma para todos: "SELECT * FROM TABLA1" para la
TABLA1, para la otra tabla la sentencia será "SELECT * FROM TABLA2"

Pues ahora el mensaje de error es: "INFRACCIÓN DE CONCURRENCIA:
UPDATECOMMAND AFECTO A 0 REGISTROS".

No hay nadie mas conectado a la bd, por cada acceso al origen de datos para
realizar alguna consulta o actualización, se realiza un open y su
corresopndiente close, con lo cual NO ENTIENDO QUE PASA y he llegado a la
conclusión de que no SE ACTUALIZAR UN DATASET CON UN DATAADAPTER.

La pregunta o la duda después de tando rollo y tanta letra: ¿Como puedo
actualizar un dataset en mi origen de datos?.

Mas Preguntas: La forma en que envio el dataset (el dataset y las consultas
sql asociadas a las tablas que tiene en su interior) a la función encargada
de realizar la operación ¿Es la correcta?, supongo que es necesario tener
las consultas sql que han llenado el dataset para poder llamar al
dataadapter.

Si solo quisiera pasarle a la función un dataset con únicamente los cambios
realizados en el mismo con el fin de optimizar el rendimiento ¿le pasaría un
dataset resultado de realizar la operación DATASET.GETCHANGES?, ¿que
información necesita el dataadapter para poder realizar la actualización
entonces?

Bueno espero haberme explicado bien, y que alguna alma caritativa sea
paciente y lea todo el texto ( Que dudo) y me pueda echar una mano en este
camino arduo y dificil que se nos plantea.

Saludos y Gracias,

Álamo.

Preguntas similare

Leer las respuestas

#1 Jesús López
13/09/2005 - 22:00 | Informe spam
La conclusión a la que llegas es errónea ya que se puede actualizar la base
de datos llamando al método DataAdapter.Update. Lo que ocurre es que es
imprescindible que el DatAdapter esté correctamente configurado, es decir,
sus propiedades UpdateCommand, InsertCommand y DeleteCommand deben estar
establecidas correctamente. Estos comandos de actualización puedes
configurarlos (a veces) automáticamente por medio de un CommandBuilder, sin
embargo la instrucción select del DataAdapter tiene que cumplir una serie de
requisitos para que esta generación automática de los comandos de
actualización sea posible. Estos requisitos son los siguientes:
1) La instrucción select sólo puede hacer referencia a una única tabla
2) La instrucción select no puede tener GROUP BY
3) La tabla de la base de datos tiene que tener una clave primaria

Si no se cumplen estas condiciones pasa lo que te está pasando a tí. En este
caso, tienes dos alternativas:
1) Configurar el dataadapter con el asistente en Visual Studio
2) Generar tú mismo por código los comandos de actualización

Saludos:

Jesús López
MVP


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

Bueno creo que por el título ya se imaginan lo que voy a preguntar.

Espero que me puedan ayudar.

Supongamos que una hermanita de la caridad nos envía un dataset con un
conjunto de datos (dos tablas por ejemplo).

Bien, nosotros como chicos buenos, mostramos la información del dataset al
usuario mediante un grid o controles normales, y además como buenos
programadores le damos la oportunidad al usuario de modificar, añadir y
borrar información de los datos almacenados en el famoso dataset.

Hasta ahí todo va bien, el problema surge cuando queremos actualizar la
información que ha generado,modificado o eliminado el usuario en el
dataset con el Origen de Datos.

He leído y releído el msdn, documentación, foros, etc pero sigo sin
resolver mi problema.

Bueno el asunto:

Yo tengo una función la cual devuelve un dataset a través de un parámetro
con una consulta sql del tipo select, es decir: Le paso una sentencia sql
y un nombre de tabla, y esta me genera un dataset con dicha consulta y
nombre de tabla:

Public Function Crear_Conjunto_Datos(ByVal sql As String, ByVal nombre As
String) As System.Data.DataSet

A su vez tengo otra función la cual mediante un dataset pasado por
parametros, y una consulta sql, añado dicha consulta sql al dataset:

Public Function Anadir_Actualizar_Conjunto_Datos(ByVal sql As String,
ByVal nombre As String, ByRef conjunto As System.Data.DataSet, ByVal modo
As String) As Boolean

Hasta ahí todo perfecto, según mi proyecto, tendré tras llamar a estas dos
funciones, un dataset con dos tablas.

Ahora quiero actualizar los datos que se encuentran en el dataset
modificado por el usuario con el Origen de Datos.

Para ello me he creado una nueva función a la cual le paso por parámetros
un dataset por referencia (byref), y las distintas consultas sql que
contiene en su interior, es decir para mi proyecto tengo dos tablas las
cuales se corresponden a dos consultas sql.

Public Function Actualizar_Conjunto_Datos_Data_Set(ByRef conjunto As
System.Data.DataSet, ByVal sql_array() As String) As Boolean

Bueno que yo sepa para realizar la actualización del dataset con el origen
de datos, tengo que utilizar un objeto dataadapter al cual, para cada
tabla del dataset pasado por parametros, inicializo con el objeto conexion
y con la consulta sql correspondiente que necesita.

m_Adaptador = New OleDbDataAdapter(sql_array(i), c_conexion)


AHORA LA PREGUNTA: Toda la documentación dice que genere un objeto
comanndbuilder para que genere de forma automática los comandos
insert,delete y update necesarios para realizar la actualización. Pues si
lo hago tal y como dice la documentación:

"cmdComando = New OleDBCommandBuilder(m_Adaptador)"

cuando me dispongo a realizar la actualización de una tabla la cual haya
sido modificada con la instrucción:

"m_Adaptador.update(DataSet,"Tabla1")"

me sale el siguiente mensaje de error: "LA GENERACION SQL DINAMICA PARA
UPDATECOMMAND NO ES COMPATIBLE CON SELECTCOMMAND, QUE NO DEVUELVE NINGUNA
INFORMACIÓN SOBRE COLUMNAS CLAVE"

Bueno yo creo que ese mensaje de error es por que no se ha inicializado el
objeto UpdateCommand del adaptador de datos. Según la documentación solo
con la instrucción anteriormente mencionada: "cmdComando = New
OleDBCommandBuilder(m_Adaptador)" el entorno de forma automática genera
los comandos pero no es así.

Añado las siguientes instrucciones:

"m_adaptador.selectcommand = new oledebcommand(sql,conexion)
m_adaptador.insertcommand = new oledbcommand(sql,conexion)
m_adaptador.deletecommand = new oledbcommand(sql,conexion)
m_adaptador.updatecommand = new oledbcommand(sql,conexion)"

la sentencia sql es la misma para todos: "SELECT * FROM TABLA1" para la
TABLA1, para la otra tabla la sentencia será "SELECT * FROM TABLA2"

Pues ahora el mensaje de error es: "INFRACCIÓN DE CONCURRENCIA:
UPDATECOMMAND AFECTO A 0 REGISTROS".

No hay nadie mas conectado a la bd, por cada acceso al origen de datos
para realizar alguna consulta o actualización, se realiza un open y su
corresopndiente close, con lo cual NO ENTIENDO QUE PASA y he llegado a la
conclusión de que no SE ACTUALIZAR UN DATASET CON UN DATAADAPTER.

La pregunta o la duda después de tando rollo y tanta letra: ¿Como puedo
actualizar un dataset en mi origen de datos?.

Mas Preguntas: La forma en que envio el dataset (el dataset y las
consultas sql asociadas a las tablas que tiene en su interior) a la
función encargada de realizar la operación ¿Es la correcta?, supongo que
es necesario tener las consultas sql que han llenado el dataset para poder
llamar al dataadapter.

Si solo quisiera pasarle a la función un dataset con únicamente los
cambios realizados en el mismo con el fin de optimizar el rendimiento ¿le
pasaría un dataset resultado de realizar la operación DATASET.GETCHANGES?,
¿que información necesita el dataadapter para poder realizar la
actualización entonces?

Bueno espero haberme explicado bien, y que alguna alma caritativa sea
paciente y lea todo el texto ( Que dudo) y me pueda echar una mano en este
camino arduo y dificil que se nos plantea.

Saludos y Gracias,

Álamo.






Respuesta Responder a este mensaje
#2 Alamo
14/09/2005 - 12:24 | Informe spam
Muchas Gracias por contestar Jesús.

Estas en lo cierto, ayer a medio día tras leer el mensaje de error 1000
veces e intentar entenderlo, comprobé el diseño de la tabla de prueba la
cual estaba actualizando y esta no tenía clave principal.

Tras habilitar el primer campo de la misma como clave principal, el objeto
commandbuilder, generó los comandos insert, delete y update de forma
automática tras indicarle el comando select, y de esta forma actualizó la
base de datos.

Muy bien, en vista a la forma en la que el entorno ADO.NET trabaja, en mi
caso, en el cual me gustaría a la hora de actualizar un data set trabajar
solo con el resultado de las modificaciones (dataset.getchanges), me obliga
siempre a almacenar las sentencias sql con las que he llenado el data set,
con el fin de poder generar el resto de comando en base al comando select.

Por casualidad no sabrás nada al respecto del método dataadapter.fillschema,
el cual según la documentación genera en el data set el esquema de la tabla
que te bajes con el fill sin datos. ¿Es necesario utilizar este método para
que el objeto commandbuilder genere de forma automática los comandos? Otra
pregunta, ¿Que tiene de cierto que el utilizar el commandbuilder genera una
consulta de mas a la base de datos para poder recuperar los metadatos y así
generar los comandos?

Saludos y gracias por contestar.



"Jesús López" escribió en el mensaje
news:
La conclusión a la que llegas es errónea ya que se puede actualizar la
base de datos llamando al método DataAdapter.Update. Lo que ocurre es que
es imprescindible que el DatAdapter esté correctamente configurado, es
decir, sus propiedades UpdateCommand, InsertCommand y DeleteCommand deben
estar establecidas correctamente. Estos comandos de actualización puedes
configurarlos (a veces) automáticamente por medio de un CommandBuilder,
sin embargo la instrucción select del DataAdapter tiene que cumplir una
serie de requisitos para que esta generación automática de los comandos de
actualización sea posible. Estos requisitos son los siguientes:
1) La instrucción select sólo puede hacer referencia a una única tabla
2) La instrucción select no puede tener GROUP BY
3) La tabla de la base de datos tiene que tener una clave primaria

Si no se cumplen estas condiciones pasa lo que te está pasando a tí. En
este caso, tienes dos alternativas:
1) Configurar el dataadapter con el asistente en Visual Studio
2) Generar tú mismo por código los comandos de actualización

Saludos:

Jesús López
MVP


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

Bueno creo que por el título ya se imaginan lo que voy a preguntar.

Espero que me puedan ayudar.

Supongamos que una hermanita de la caridad nos envía un dataset con un
conjunto de datos (dos tablas por ejemplo).

Bien, nosotros como chicos buenos, mostramos la información del dataset
al usuario mediante un grid o controles normales, y además como buenos
programadores le damos la oportunidad al usuario de modificar, añadir y
borrar información de los datos almacenados en el famoso dataset.

Hasta ahí todo va bien, el problema surge cuando queremos actualizar la
información que ha generado,modificado o eliminado el usuario en el
dataset con el Origen de Datos.

He leído y releído el msdn, documentación, foros, etc pero sigo sin
resolver mi problema.

Bueno el asunto:

Yo tengo una función la cual devuelve un dataset a través de un parámetro
con una consulta sql del tipo select, es decir: Le paso una sentencia sql
y un nombre de tabla, y esta me genera un dataset con dicha consulta y
nombre de tabla:

Public Function Crear_Conjunto_Datos(ByVal sql As String, ByVal nombre As
String) As System.Data.DataSet

A su vez tengo otra función la cual mediante un dataset pasado por
parametros, y una consulta sql, añado dicha consulta sql al dataset:

Public Function Anadir_Actualizar_Conjunto_Datos(ByVal sql As String,
ByVal nombre As String, ByRef conjunto As System.Data.DataSet, ByVal modo
As String) As Boolean

Hasta ahí todo perfecto, según mi proyecto, tendré tras llamar a estas
dos funciones, un dataset con dos tablas.

Ahora quiero actualizar los datos que se encuentran en el dataset
modificado por el usuario con el Origen de Datos.

Para ello me he creado una nueva función a la cual le paso por parámetros
un dataset por referencia (byref), y las distintas consultas sql que
contiene en su interior, es decir para mi proyecto tengo dos tablas las
cuales se corresponden a dos consultas sql.

Public Function Actualizar_Conjunto_Datos_Data_Set(ByRef conjunto As
System.Data.DataSet, ByVal sql_array() As String) As Boolean

Bueno que yo sepa para realizar la actualización del dataset con el
origen de datos, tengo que utilizar un objeto dataadapter al cual, para
cada tabla del dataset pasado por parametros, inicializo con el objeto
conexion y con la consulta sql correspondiente que necesita.

m_Adaptador = New OleDbDataAdapter(sql_array(i), c_conexion)


AHORA LA PREGUNTA: Toda la documentación dice que genere un objeto
comanndbuilder para que genere de forma automática los comandos
insert,delete y update necesarios para realizar la actualización. Pues si
lo hago tal y como dice la documentación:

"cmdComando = New OleDBCommandBuilder(m_Adaptador)"

cuando me dispongo a realizar la actualización de una tabla la cual haya
sido modificada con la instrucción:

"m_Adaptador.update(DataSet,"Tabla1")"

me sale el siguiente mensaje de error: "LA GENERACION SQL DINAMICA PARA
UPDATECOMMAND NO ES COMPATIBLE CON SELECTCOMMAND, QUE NO DEVUELVE NINGUNA
INFORMACIÓN SOBRE COLUMNAS CLAVE"

Bueno yo creo que ese mensaje de error es por que no se ha inicializado
el objeto UpdateCommand del adaptador de datos. Según la documentación
solo con la instrucción anteriormente mencionada: "cmdComando = New
OleDBCommandBuilder(m_Adaptador)" el entorno de forma automática genera
los comandos pero no es así.

Añado las siguientes instrucciones:

"m_adaptador.selectcommand = new oledebcommand(sql,conexion)
m_adaptador.insertcommand = new oledbcommand(sql,conexion)
m_adaptador.deletecommand = new oledbcommand(sql,conexion)
m_adaptador.updatecommand = new oledbcommand(sql,conexion)"

la sentencia sql es la misma para todos: "SELECT * FROM TABLA1" para la
TABLA1, para la otra tabla la sentencia será "SELECT * FROM TABLA2"

Pues ahora el mensaje de error es: "INFRACCIÓN DE CONCURRENCIA:
UPDATECOMMAND AFECTO A 0 REGISTROS".

No hay nadie mas conectado a la bd, por cada acceso al origen de datos
para realizar alguna consulta o actualización, se realiza un open y su
corresopndiente close, con lo cual NO ENTIENDO QUE PASA y he llegado a la
conclusión de que no SE ACTUALIZAR UN DATASET CON UN DATAADAPTER.

La pregunta o la duda después de tando rollo y tanta letra: ¿Como puedo
actualizar un dataset en mi origen de datos?.

Mas Preguntas: La forma en que envio el dataset (el dataset y las
consultas sql asociadas a las tablas que tiene en su interior) a la
función encargada de realizar la operación ¿Es la correcta?, supongo que
es necesario tener las consultas sql que han llenado el dataset para
poder llamar al dataadapter.

Si solo quisiera pasarle a la función un dataset con únicamente los
cambios realizados en el mismo con el fin de optimizar el rendimiento ¿le
pasaría un dataset resultado de realizar la operación
DATASET.GETCHANGES?, ¿que información necesita el dataadapter para poder
realizar la actualización entonces?

Bueno espero haberme explicado bien, y que alguna alma caritativa sea
paciente y lea todo el texto ( Que dudo) y me pueda echar una mano en
este camino arduo y dificil que se nos plantea.

Saludos y Gracias,

Álamo.










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