net - Usando OleDbDataAdapter para actualizar un DataTable C#
sqldataadapter fill datatable (2)
He intentado usar OleDbDataAdapter para actualizar una DataTable, pero me confundieron los comandos. Como a veces obtengo información de diferentes tablas, no puedo usar CommandBuilder. Así que intenté crear los comandos en mi on pero me resultó difícil con los parámetros. DataTable.GetChanges devuelve filas que necesitan usar un INSERT o un comando UPDATE - Supongo que no puedo distinguir entre ellos. Necesito que completes lo siguiente:
DataTable dt = new DataTable();
OleDbDataAdapter da = new OleDbDataAdapter();
// Here I create the SELECT command and pass the connection.
da.Fill(dt);
// Here I make changes (INSERT/UPDATE) to the DataTable (by a DataGridView).
da.UpdateCommand = new OleDbCommand("UPDATE TABLE_NAME SET (COL1, COL2, ...) VALUES (@newVal1, @newVal2, ...) WHERE id=@id"); // How can I use the values of the current row (that the da is updating) as the parameters (@newVal1, @newVal2, id....)?
¡Muchas gracias!
Podría usar el método String.Format para reemplazar @newVal1, @newVal2, ...
en su código, como este da.UpdateCommand = new OleDbCommand(String.Format("UPDATE TABLE_NAME SET (COL1, COL2, ...) VALUES ({0}, {1}, ...) WHERE id=@id",OBJECT_ARRAY_CONTAINING_VALUES_FROM_THEDG));
[Eidt por comentario]
Para manejar la row[0]
, row[1]
necesita un bucle como:
for(i=0; i<rows.Count; i++) {
da.UpdateCommand = new OleDbCommand(String.Format("UPDATE
... ",row[i]);
da.Update(dt);
}
El adaptador de datos puede funcionar junto con la tabla de datos. Como tal, he envuelto a los míos en una clase y funciona bastante bien. Además de las complejidades de mis cosas, aquí hay un fragmento que podría ayudarte. Al agregar un parámetro, puede identificar el origen de la columna de donde provienen los datos FROM DataTable. De esta forma, cuando un registro se identifica internamente como "Agregado" o "Actualizado" (o "Eliminado"), cuando crea los comandos Insertar / Actualizar / Eliminar de SQL, extraerá los datos de las columnas de las filas respectivas.
Por ejemplo. Supongamos que tengo una DataTable, la clave principal es "MyID" y tiene columnas "ColX, ColY, ColZ". Creo mi DataAdapter y construyo mis comandos select, update, delete como ... (? Es un marcador de posición para los parámetros)
DataAdapter myAdapter = new DataAdapter()
myAdapter.SelectCommand = new OleDbCommand();
myAdapter.InsertCommand = new OleDbCommand();
myAdapter.UpdateCommand = new OleDbCommand();
myAdapter.DeleteCommand = new OleDbCommand();
myAdapter.SelectCommand.CommandText = "select * from MyTable where MyID = ?";
myAdapter.InsertCommand.CommandText = "insert into MyTable ( ColX, ColY, ColZ ) values ( ?, ?, ? )";
myAdapter.UpdateCommand.CommandText = "update MyTable set ColX = ?, ColY = ?, ColZ = ? where MyID = ?";
myAdapter.DeleteCommand.CommandText = "delete from MyTable where MyID = ?";
Ahora, cada uno tiene que tener sus respectivos "Parámetros". Los parámetros deben agregarse en la misma secuencia que su correspondiente "?" Place-Holders.
// Aunque estoy poniendo valores falsos para preparar los parámetros, es solo para // tipos de datos. Se cambia a través del adaptador de datos cuando aplica los cambios
OleDbParameter oParm = new OleDbParameter( "myID", -1 );
oParm.DbType = DbType.Int32;
oParm.SourceColumn = "myID"; // <- this is where it looks back to source table''s column
oParm.ParameterName = "myID"; // just for consistency / readability reference
myAdapter.SelectCommand.Parameters.Add( oParm );
hacer similar para el resto de los parámetros en función de sus tipos ... char, int, double, whatever
De nuevo, tengo como una clase contenedora que maneja la administración por tabla ... en resumen
public myClassWrapper
{
protected DataTable myTable;
protected DataAdapter myAdapter;
... more ...
protected void SaveChanges()
{
}
}
Es más complejo que esto, pero durante el "SaveChanges", Datatable y dataAdapter están sincronizados para sus propios fines. Ahora, vaciando los datos. Compruebo el estado de la tabla y luego puede pasar toda la tabla al dataAdapter para la actualización y recorrerá todos los registros modificados e impulsará los cambios respectivos. Sin embargo, tendrás que atrapar cualquier posible error de datos.
myAdapter.Update( this.MyTable );
A medida que encuentra cada registro "modificado", extrae los valores de la Fuente de columna identificados por el parámetro que se encuentra en la tabla que se está transfiriendo al adaptador para su procesamiento.
Espero que esto te haya dado un gran salto en lo que te estás encontrando.
---- COMENTARIO POR RETROALIMENTACIÓN ----
Pondré tu actualización dentro de un try / catch, y entraré al programa para ver cuál es la excepción. El mensaje adn / o la excepción interna del error podría dar más información. Sin embargo, intente simplificar su ACTUALIZACIÓN para incluir solo algunos campos con el elemento DONDE "Clave".
Además, y dije, me perdí esto de la respuesta de la primera parte. Es posible que deba identificar la columna "Clave principal" de la tabla de datos. Para hacerlo, es una propiedad del DataTable que espera y una matriz de columnas que representan la clave principal para la tabla. Lo que hice fue ...
// set the primary key column of the table
DataColumn[] oCols = { myDataTbl.Columns["myID"] };
myDataTbl.PrimaryKey = oCols;
Me gustaría comentar su cadena de actualización completa y todos sus parámetros para su ACTUALIZACIÓN. Luego, contruya con tan simple como mi muestra de solo establecer 2-3 columnas y la cláusula where
myAdapter.UpdateCommand.CommandText = "update MyTable set ColX = ?, ColY = ? where MyID=?";
Add Parameter object for "X"
Add Parameter object for "Y"
Add Parameter object for "MyID"
Seleccione campos como int o char para que tengan la menor probabilidad de problemas para las conversiones de tipos de datos; luego, una vez que funcionen, intente agregar todas sus columnas "int" y "character" ... luego agregue las demás. Además, ¿a qué base de datos estás yendo en contra? ALGUNAS bases de datos no usan "?" como marcador de posición en el comando pero usa parámetros "nombrados", algunos usan
"actualColumn = @namedCol"
or even
"actualColumn = :namedCol"
Espero que esto te lleve a la cima ...