Operaciones por lotes con objetos DataAdapter
Se aplica a: .NET Framework .NET .NET Standard
La compatibilidad con las operaciones por lotes en ADO.NET permite que un DataAdapter agrupe operaciones INSERT, UPDATE y DELETE desde un DataSet o una DataTable al servidor, en lugar de enviar las operaciones de una en una. La reducción del número de viajes de ida y vuelta (round trip) al servidor tiene como resultado una mejora considerable del rendimiento. Se admite la actualización por lotes para el proveedor de datos SqlClient de Microsoft para SQL Server (Microsoft.Data.SqlClient).
Al actualizar una base de datos con modificaciones de un DataSet en versiones anteriores de ADO.NET, el método Update
de un DataAdapter
realizaba actualizaciones de las filas de la base de datos de una en una. A medida que recorría las filas de la DataTable especificada, examinaba cada DataRow para ver si se había modificado. Si se había modificado la fila, llamaba al UpdateCommand
, InsertCommand
o DeleteCommand
apropiado, en función del valor de propiedad RowState de la fila. Cada actualización de una fila implicaba un viaje de ida y vuelta (round trip) a la base de datos.
En el proveedor de datos SqlClient de Microsoft para SQL Server, SqlDataAdapter expone una propiedad UpdateBatchSize. Si se establece el UpdateBatchSize
en un valor entero positivo, se producen actualizaciones en la base de datos que se envían como lotes del tamaño especificado. Por ejemplo, si se establece el UpdateBatchSize
en 10, se agrupan 10 instrucciones separadas y se envían en un único lote. Si se establece el UpdateBatchSize
en 0, el SqlDataAdapter utilizará el mayor tamaño de lote admitido por el servidor. Si se establece el valor en 1, se deshabilitan las actualizaciones por lotes y las filas se envían de una en una.
Nota
Si se ejecuta un lote demasiado grande, el rendimiento podría verse afectado. Por tanto, es conveniente realizar pruebas a fin de determinar el valor óptimo del tamaño del lote antes de implementar la aplicación.
Uso de la propiedad UpdateBatchSize
Al habilitar las actualizaciones por lotes, el valor de propiedad UpdatedRowSource de UpdateCommand
, InsertCommand
y DeleteCommand
del DataAdapter debe establecerse en None o OutputParameters. Al realizar una actualización por lotes, el valor UpdatedRowSource o FirstReturnedRecord de la propiedad Both del comando no es válido.
En el siguiente procedimiento se muestra cómo se utiliza la propiedad UpdateBatchSize
. En el procedimiento se toman dos argumentos, un objeto DataSet con columnas que representan los campos ProductCategoryID y Name de la tabla Production.ProductCategory, y un entero que representa el tamaño del lote (el número de filas). El código crea un objeto SqlDataAdapter nuevo y se establecen las propiedades UpdateCommand, InsertCommand y DeleteCommand. En el código se supone que el objeto DataSet tiene filas modificadas. Se establece la propiedad UpdateBatchSize
y se ejecuta la actualización.
public static void BatchUpdate(DataTable dataTable, Int32 batchSize)
{
// Assumes GetConnectionString() returns a valid connection string.
string connectionString = GetConnectionString();
// Connect to the AdventureWorks database.
using (SqlConnection connection = new SqlConnection(connectionString))
{
// Create a SqlDataAdapter.
SqlDataAdapter adapter = new SqlDataAdapter();
// Set the UPDATE command and parameters.
adapter.UpdateCommand = new SqlCommand(
"UPDATE Production.ProductCategory SET "
+ "Name=@Name WHERE ProductCategoryID=@ProdCatID;",
connection);
adapter.UpdateCommand.Parameters.Add("@Name",
SqlDbType.NVarChar, 50, "Name");
adapter.UpdateCommand.Parameters.Add("@ProdCatID",
SqlDbType.Int, 4, "ProductCategoryID");
adapter.UpdateCommand.UpdatedRowSource = UpdateRowSource.None;
// Set the INSERT command and parameter.
adapter.InsertCommand = new SqlCommand(
"INSERT INTO Production.ProductCategory (Name) VALUES (@Name);",
connection);
adapter.InsertCommand.Parameters.Add("@Name",
SqlDbType.NVarChar, 50, "Name");
adapter.InsertCommand.UpdatedRowSource = UpdateRowSource.None;
// Set the DELETE command and parameter.
adapter.DeleteCommand = new SqlCommand(
"DELETE FROM Production.ProductCategory "
+ "WHERE ProductCategoryID=@ProdCatID;", connection);
adapter.DeleteCommand.Parameters.Add("@ProdCatID",
SqlDbType.Int, 4, "ProductCategoryID");
adapter.DeleteCommand.UpdatedRowSource = UpdateRowSource.None;
// Set the batch size.
adapter.UpdateBatchSize = batchSize;
// Execute the update.
adapter.Update(dataTable);
}
}
Control de errores y eventos relacionados con la actualización por lotes
DataAdapter tiene dos eventos relacionados con la actualización: RowUpdating y RowUpdated. Para obtener más información, vea Control de eventos de objetos DataAdapter.
Cambios de comportamiento de eventos con actualizaciones por lotes
Si se habilita el procesamiento por lotes, se actualizan varias filas en una única operación de base de datos. Por tanto, solo se produce un evento RowUpdated
para cada lote, mientras que el evento RowUpdating
se produce para cada fila procesada. Si se deshabilita el procesamiento por lotes, los dos eventos se activan con entrelazado individualizado, donde los eventos RowUpdating
y RowUpdated
se activan para una fila y, a continuación, se activan los eventos RowUpdating
y RowUpdated
para la siguiente fila, hasta que se hayan procesado todas las filas.
Acceso a filas actualizadas
Si se deshabilita el procesamiento por lotes, se puede obtener acceso a la fila que se está actualizando mediante la propiedad Row de la clase RowUpdatedEventArgs.
Cuando se habilita el procesamiento por lotes, se genera un único evento RowUpdated
para varias filas. Por tanto, el valor de la propiedad Row
para cada fila es nulo. Aun así, los eventos RowUpdating
se generarán para cada fila. El método CopyToRows de la clase RowUpdatedEventArgs permite obtener acceso a las filas procesadas al copiar referencias a las mismas en una matriz. Si no se está procesando ninguna fila, CopyToRows
inicia una ArgumentNullException. Utilice la propiedad RowCount para devolver el número de filas procesadas antes de llamar al método CopyToRows.
Control de errores de datos
La ejecución por lotes tiene el mismo efecto que la ejecución de cada instrucción por separado. Las instrucciones se ejecutan en el mismo orden en el que se agregaron al lote. Los errores se controlan de la misma forma en el modo de procesamiento por lotes que cuando éste se encuentra deshabilitado. Cada fila se procesa por separado. Solo aquellas filas procesadas correctamente en la base de datos se actualizarán en la DataRow correspondiente dentro de la DataTable.
Nota
El proveedor de datos SqlClient de Microsoft SQL Server y el servidor de base de datos de back-end determinan qué construcciones SQL se admiten para la ejecución por lotes. Es posible que se inicie una excepción si se envía una instrucción no compatible para su ejecución.