Выполнение пакетных операций с использованием объектов DataAdaptersPerforming Batch Operations Using DataAdapters

Поддержка пакетных операций в ADO.NET позволяет объекту DataAdapter группировать операции INSERT, UPDATE и DELETE из DataSet или DataTable к серверу вместо отправки за один раз одной операции.Batch support in ADO.NET allows a DataAdapter to group INSERT, UPDATE, and DELETE operations from a DataSet or DataTable to the server, instead of sending one operation at a time. Уменьшение числа двусторонних передач сигнала на сервер обычно приводит к значительному повышению производительности.The reduction in the number of round trips to the server typically results in significant performance gains. Пакетные обновления поддерживаются для поставщиков .NET-данных для SQL Server (System.Data.SqlClient) и Oracle (System.Data.OracleClient).Batch updates are supported for the .NET data providers for SQL Server (System.Data.SqlClient) and Oracle (System.Data.OracleClient).

При обновлении базы данных изменениями из объекта DataSet в более ранних версиях ADO.NET метод Update для DataAdapter выполняет обновления в базе данных по одной строке.When updating a database with changes from a DataSet in previous versions of ADO.NET, the Update method of a DataAdapter performed updates to the database one row at a time. Когда он просматривает строки в указанной таблице DataTable, он проверяет каждую строку DataRow, чтобы выявить, не была ли она изменена.As it iterated through the rows in the specified DataTable, it examined each DataRow to see if it had been modified. Если строка изменена, он вызывает соответствующую команду UpdateCommand, InsertCommand или DeleteCommand в зависимости от значения свойства RowState для этой строки.If the row had been modified, it called the appropriate UpdateCommand, InsertCommand, or DeleteCommand, depending on the value of the RowState property for that row. Каждое обновление строки подразумевает сетевую двустороннюю передачу сигнала в базу данных.Every row update involved a network round-trip to the database.

Начиная с ADO.NET 2.0, объект DbDataAdapter предоставляет свойство UpdateBatchSize.Starting with ADO.NET 2.0, the DbDataAdapter exposes an UpdateBatchSize property. При установке для свойства UpdateBatchSize положительного целого значения обновления базы данных посылаются как пакеты указанного размера.Setting the UpdateBatchSize to a positive integer value causes updates to the database to be sent as batches of the specified size. Например, при установке UpdateBatchSize в 10 производится группирование 10 отдельных инструкций и передача их как один пакет.For example, setting the UpdateBatchSize to 10 will group 10 separate statements and submit them as single batch. При установке UpdateBatchSize в 0 DataAdapter использует самой большой размер пакета, который может обработать сервер.Setting the UpdateBatchSize to 0 will cause the DataAdapter to use the largest batch size that the server can handle. При его установке в 1 отключаются пакетные обновления, т. к. строки посылаются по одной.Setting it to 1 disables batch updates, as rows are sent one at a time.

Выполнение очень больших пакетов может снизить производительность.Executing an extremely large batch could decrease performance. Поэтому необходимо экспериментальным путем найти параметр оптимального размера пакета перед реализацией приложения.Therefore, you should test for the optimum batch size setting before implementing your application.

Использование свойства UpdateBatchSizeUsing the UpdateBatchSize Property

Если пакетные обновления включены, значение свойства UpdatedRowSource для UpdateCommand, InsertCommand и DeleteCommand объекта DataAdapter должно быть установлено в None или OutputParameters.When batch updates are enabled, the UpdatedRowSource property value of the DataAdapter's UpdateCommand, InsertCommand, and DeleteCommand should be set to None or OutputParameters. При выполнении пакетного обновления значение свойства UpdatedRowSource команды для FirstReturnedRecord или Both недействительно.When performing a batch update, the command's UpdatedRowSource property value of FirstReturnedRecord or Both is invalid.

Следующая процедура демонстрирует использование свойства UpdateBatchSize.The following procedure demonstrates the use of the UpdateBatchSize property. DataSet Процедура принимает два аргумента — объект со столбцами, представляющими поля ProductCategoryID и Name в таблице Production. ProductCategory , и целое число, представляющее размер пакета (число строк в пакете).The procedure takes two arguments, a DataSet object that has columns representing the ProductCategoryID and Name fields in the Production.ProductCategory table, and an integer representing the batch size (the number of rows in the batch). Код создает новый объект SqlDataAdapter, устанавливая его свойства UpdateCommand, InsertCommand и DeleteCommand.The code creates a new SqlDataAdapter object, setting its UpdateCommand, InsertCommand, and DeleteCommand properties. В коде предполагается, что объект DataSet имеет измененные строки.The code assumes that the DataSet object has modified rows. В нем устанавливается свойство UpdateBatchSize и выполняется обновление.It sets the UpdateBatchSize property and executes the update.

Public Sub BatchUpdate( _  
  ByVal dataTable As DataTable, ByVal batchSize As Int32)  
    ' Assumes GetConnectionString() returns a valid connection string.  
    Dim connectionString As String = GetConnectionString()  
  
    ' Connect to the AdventureWorks database.  
    Using connection As New SqlConnection(connectionString)  
        ' Create a SqlDataAdapter.  
        Dim adapter As 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)  
    End Using  
End Sub  
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);  
    }  
}  

У DataAdapter есть два события, связанных с обновлением: RowUpdating и RowUpdated.The DataAdapter has two update-related events: RowUpdating and RowUpdated. В более ранних версиях ADO.NET, если пакетная обработка отключена, каждое из этих событий формируется для каждой обрабатываемой строки.In previous versions of ADO.NET, when batch processing is disabled, each of these events is generated once for each row processed. Событие RowUpdating создается до выполнения обновления, а событие RowUpdated создается после завершения обновления базы данных.RowUpdating is generated before the update occurs, and RowUpdated is generated after the database update has been completed.

Изменение поведения событий при пакетных обновленияхEvent Behavior Changes with Batch Updates

Если пакетное обновление включено, несколько строк обновляются одной операцией базы данных.When batch processing is enabled, multiple rows are updated in a single database operation. Поэтому для каждого пакета происходит только одно событие RowUpdated, в то время как событие RowUpdating происходит для каждой обрабатываемой строки.Therefore, only one RowUpdated event occurs for each batch, whereas the RowUpdating event occurs for each row processed. Если пакетное обновление отключено, два события инициируются с чередованием один к одному, где одно событие RowUpdating и одно событие RowUpdated инициируется для строки, а затем одно событие RowUpdating и одно событие RowUpdated инициируются для следующей строки, до тех пор пока не будут обработаны все строки.When batch processing is disabled, the two events are fired with one-to-one interleaving, where one RowUpdating event and one RowUpdated event fire for a row, and then one RowUpdating and one RowUpdated event fire for the next row, until all of the rows are processed.

Доступ к обновленным строкамAccessing Updated Rows

Если пакетная обработка отключена, доступ к обновляемой строке может быть выполнен при помощи свойства Row класса RowUpdatedEventArgs.When batch processing is disabled, the row being updated can be accessed using the Row property of the RowUpdatedEventArgs class.

Если пакетная обработка включена для нескольких строк, формируется одно событие RowUpdated.When batch processing is enabled, a single RowUpdated event is generated for multiple rows. Поэтому значение свойства Row для каждой из строк равно NULL.Therefore, the value of the Row property for each row is null. События RowUpdating по-прежнему вызываются для каждой строки.RowUpdating events are still generated for each row. Метод CopyToRows класса RowUpdatedEventArgs позволяет обращаться к обработанным строкам, копируя ссылки на строки в массив.The CopyToRows method of the RowUpdatedEventArgs class allows you to access the processed rows by copying references to the rows into an array. Если строки не обрабатываются, метод CopyToRows инициирует исключение ArgumentNullException.If no rows are being processed, CopyToRows throws an ArgumentNullException. Свойство RowCount используется для возврата числа строк, обработанных перед вызовом метода CopyToRows.Use the RowCount property to return the number of rows processed before calling the CopyToRows method.

Обработка ошибок данныхHandling Data Errors

Пакетное выполнение оказывает то же влияние, что и выполнение каждой отдельной инструкции.Batch execution has the same effect as the execution of each individual statement. Инструкции выполняются в порядке, который инструкции добавили в пакет.Statements are executed in the order that the statements were added to the batch. Ошибки обрабатываются в пакетном режиме, как если было бы при отключении пакетного режима.Errors are handled the same way in batch mode as they are when batch mode is disabled. Каждая строка обрабатывается отдельно.Each row is processed separately. Только успешно обработанные в базе данных строки будут обновлены в соответствующей строке DataRow таблицы DataTable.Only rows that have been successfully processed in the database will be updated in the corresponding DataRow within the DataTable.

Поставщик данных и сервер базы данных определяют, какие конструкции SQL поддерживаются для пакетного обновления.The data provider and the back-end database server determine which SQL constructs are supported for batch execution. Если неподдерживаемая инструкция подается на выполнение, создается исключение.An exception may be thrown if a non-supported statement is submitted for execution.

См. такжеSee also