Generar comandos con objetos CommandBuilderGenerating Commands with CommandBuilders

Cuando la propiedad SelectCommand se especifica de forma dinámica en tiempo de ejecución, por ejemplo a través de una herramienta de consulta que acepta un comando de texto del usuario, existe la posibilidad de que no se pueda especificar adecuadamente en tiempo de diseño el comando InsertCommand, UpdateCommand o DeleteCommand correspondiente.When the SelectCommand property is dynamically specified at run time, such as through a query tool that takes a textual command from the user, you may not be able to specify the appropriate InsertCommand, UpdateCommand, or DeleteCommand at design time. Si el objeto DataTable se asigna a una única tabla de base de datos o se genera a partir de ella, puede utilizar el objeto DbCommandBuilder para generar automáticamente las propiedades DeleteCommand, InsertCommand y UpdateCommand de DbDataAdapter.If your DataTable maps to or is generated from a single database table, you can take advantage of the DbCommandBuilder object to automatically generate the DeleteCommand, InsertCommand, and UpdateCommand of the DbDataAdapter.

El requisito mínimo para que la generación automática de comandos funcione correctamente consiste en establecer la propiedad SelectCommand.As a minimum requirement, you must set the SelectCommand property in order for automatic command generation to work. El esquema de tabla que recupera la propiedad SelectCommand determina la sintaxis de las instrucciones INSERT, UPDATE y DELETE generadas automáticamente.The table schema retrieved by the SelectCommand property determines the syntax of the automatically generated INSERT, UPDATE, and DELETE statements.

DbCommandBuilder debe ejecutar SelectCommand con el objeto de devolver los metadatos necesarios para construir los comandos SQL INSERT, UPDATE y DELETE.The DbCommandBuilder must execute the SelectCommand in order to return the metadata necessary to construct the INSERT, UPDATE, and DELETE SQL commands. Por eso es necesario realizar un viaje adicional al origen de datos, con el consiguiente efecto adverso en el rendimiento.As a result, an extra trip to the data source is necessary, and this can hinder performance. Para mejorar el rendimiento, debe especificar los comandos de forma explícita, en lugar de utilizar DbCommandBuilder.To achieve optimal performance, specify your commands explicitly rather than using the DbCommandBuilder.

SelectCommand también debe devolver como mínimo una clave principal o una columna única.The SelectCommand must also return at least one primary key or unique column. Si no hay ninguna, se genera una excepción InvalidOperation y no se genera ningún comando.If none are present, an InvalidOperation exception is generated, and the commands are not generated.

Cuando se asocia con un objeto DataAdapter, DbCommandBuilder genera automáticamente las propiedades InsertCommand, UpdateCommand y DeleteCommand del objeto DataAdapter si son referencias nulas.When associated with a DataAdapter, the DbCommandBuilder automatically generates the InsertCommand, UpdateCommand, and DeleteCommand properties of the DataAdapter if they are null references. Si ya existe algún objeto Command para una propiedad, se utilizará el objeto Command existente.If a Command already exists for a property, the existing Command is used.

Las vistas de bases de datos creadas al unir una o varias tablas no se consideran una tabla única de base de datos.Database views that are created by joining two or more tables together are not considered a single database table. En este caso no puede utilizar DbCommandBuilder para generar comandos automáticamente y deberá especificarlos de manera explícita.In this instance you cannot use the DbCommandBuilder to automatically generate commands; you must specify your commands explicitly. Para obtener información sobre cómo establecer DataSet explícitamente comandos para resolver actualizaciones de una copia posterior en el origen de datos, vea Actualizar orígenes de datos con DataAdapters.For information about explicitly setting commands to resolve updates to a DataSet back to the data source, see Updating Data Sources with DataAdapters.

Es posible que desee asignar parámetros de salida a la fila actualizada de un DataSet.You might want to map output parameters back to the updated row of a DataSet. Una tarea habitual consiste en recuperar, a partir del origen de datos, el valor de un campo de identidad de generación automática o una marca de tiempo.One common task would be retrieving the value of an automatically generated identity field or time stamp from the data source. DbCommandBuilder no asigna de forma predeterminada los parámetros de salida a las columnas de una fila actualizada.The DbCommandBuilder will not map output parameters to columns in an updated row by default. En este caso, debe especificar el comando de forma explícita.In this instance you must specify your command explicitly. Para obtener un ejemplo de asignación de un campo de identidad generado automáticamente a una columna de una fila insertada, vea Recuperar valores de identidad o numeración automática.For an example of mapping an automatically generated identity field back to a column of an inserted row, see Retrieving Identity or Autonumber Values.

Reglas para comandos generados automáticamenteRules for Automatically Generated Commands

En la tabla siguiente se muestran las reglas de la generación automática de comandos.The following table shows the rules for how automatically generated commands are generated.

Get-HelpCommand ReglaRule
InsertCommand Inserta una fila en el origen de datos para todas las filas de la tabla con una RowState con el valor Added.Inserts a row at the data source for all rows in the table with a RowState of Added. Inserta valores para todas las columnas actualizables, pero no para determinadas columnas como identidades, expresiones o marcas de tiempo.Inserts values for all columns that are updateable (but not columns such as identities, expressions, or timestamps).
UpdateCommand Actualiza filas en el origen de datos para todas las filas de la tabla con una propiedad RowState con el valor Modified.Updates rows at the data source for all rows in the table with a RowState of Modified. Actualiza los valores de todas las columnas, con excepción de las que no son actualizables, como identidades o expresiones.Updates the values of all columns except for columns that are not updateable, such as identities or expressions. Actualiza todas las filas en las que los valores de columna en el origen de datos coinciden con los valores de la columna de clave principal de la fila, siempre que las restantes columnas del origen de datos coincidan con los valores originales de la fila.Updates all rows where the column values at the data source match the primary key column values of the row, and where the remaining columns at the data source match the original values of the row. Para obtener más información, vea la sección "Modelo de simultaneidad optimista para actualizaciones y eliminaciones" de este mismo tema.For more information, see "Optimistic Concurrency Model for Updates and Deletes," later in this topic.
DeleteCommand Elimina filas en el origen de datos para todas las filas de la tabla con una propiedad RowState con el valor Deleted.Deletes rows at the data source for all rows in the table with a RowState of Deleted. Elimina todas las filas en las que los valores de columna coinciden con los valores de la columna de clave principal de la fila, siempre que las restantes columnas del origen de datos coincidan con los valores originales de la fila.Deletes all rows where the column values match the primary key column values of the row, and where the remaining columns at the data source match the original values of the row. Para obtener más información, vea la sección "Modelo de simultaneidad optimista para actualizaciones y eliminaciones" de este mismo tema.For more information, see "Optimistic Concurrency Model for Updates and Deletes," later in this topic.

Modelo de simultaneidad optimista para actualizaciones y eliminacionesOptimistic Concurrency Model for Updates and Deletes

La lógica para generar comandos automáticamente para las instrucciones UPDATE y DELETE se basa en la simultaneidad optimista, es decir, los registros no están bloqueados para su edición y pueden ser modificados por otros usuarios o procesos en cualquier momento.The logic for generating commands automatically for UPDATE and DELETE statements is based on optimistic concurrency--that is, records are not locked for editing and can be modified by other users or processes at any time. Dado que existe la posibilidad de que un registro haya sido modificado después de que haya sido devuelto por la instrucción SELECT y antes de que se emita la instrucción UPDATE o DELETE, la instrucción UPDATE o DELETE generada automáticamente incluye una cláusula WHERE que especifica que la fila solo se actualiza cuando contiene todos los valores originales y no ha sido eliminada del origen de datos.Because a record could have been modified after it was returned from the SELECT statement, but before the UPDATE or DELETE statement is issued, the automatically generated UPDATE or DELETE statement contains a WHERE clause, specifying that a row is only updated if it contains all original values and has not been deleted from the data source. Esto evita que se sobrescriban los datos nuevos.This is done to avoid overwriting new data. Si una actualización generada automáticamente intenta actualizar una fila que ha sido eliminada o que no contiene los valores originales del DataSet, el comando no tienen ningún efecto en los registros y se inicia una excepción DBConcurrencyException.Where an automatically generated update attempts to update a row that has been deleted or that does not contain the original values found in the DataSet, the command does not affect any records, and a DBConcurrencyException is thrown.

Si desea que la instrucción UPDATE o DELETE se ejecute sin tener en cuenta los valores originales, debe establecer de forma explícita la propiedad UpdateCommand del DataAdapter sin utilizar la generación automática de comandos.If you want the UPDATE or DELETE to complete regardless of original values, you must explicitly set the UpdateCommand for the DataAdapter and not rely on automatic command generation.

Limitaciones de la lógica de generación automática de comandosLimitations of Automatic Command Generation Logic

La generación automática de comandos tiene las siguientes limitaciones.The following limitations apply to automatic command generation.

Solo tablas no relacionadasUnrelated Tables Only

La lógica de generación automática de comandos crea instrucciones INSERT, UPDATE o DELETE para tablas independientes sin tener en cuenta las relaciones que éstas puedan tener con otras tablas en el origen de datos.The automatic command generation logic generates INSERT, UPDATE, or DELETE statements for stand-alone tables without taking into account any relationships to other tables at the data source. Por eso, se puede producir un error al llamar a Update para realizar cambios en una columna que participa de una restricción de clave externa en la base de datos.As a result, you may encounter a failure when calling Update to submit changes for a column that participates in a foreign key constraint in the database. Para evitar esa excepción, no utilice DbCommandBuilder al actualizar las columnas que participan en una restricción de clave externa. En este caso debe especificar de forma explícita las instrucciones que se van a utilizar para llevar a cabo la operación.To avoid this exception, do not use the DbCommandBuilder for updating columns involved in a foreign key constraint; instead, explicitly specify the statements used to perform the operation.

Nombres de tabla y columnaTable and Column Names

La lógica de generación automática de comandos puede ocasionar un error cuando los nombres de las tablas o de las columnas incluyen algún carácter especial, como espacios, puntos, comillas y otros caracteres no alfanuméricos, incluso si están delimitados por corchetes.Automatic command generation logic may fail if column names or table names contain any special characters, such as spaces, periods, quotation marks, or other nonalphanumeric characters, even if delimited by brackets. En función del proveedor, el establecimiento de los parámetros QuotePrefix y QuoteSuffix puede permitir que la lógica de generación procese espacios, pero los caracteres especiales no pueden convertirse en caracteres de escape.Depending on the provider, setting the QuotePrefix and QuoteSuffix parameters may allow the generation logic to process spaces, but it cannot escape special characters. Se admiten nombres de tabla completos en forma de catalog.schema.table.Fully qualified table names in the form of catalog.schema.table are supported.

Utilizar CommandBuilder para generar automáticamente una instrucción SQLUsing the CommandBuilder to Automatically Generate an SQL Statement

Para generar instrucciones SQL automáticamente para un DataAdapter, defina en primer lugar la propiedad SelectCommand del DataAdapter y, a continuación, cree un objeto CommandBuilder y especifique como argumento el DataAdapter para el que CommandBuilder generará automáticamente las instrucciones SQL.To automatically generate SQL statements for a DataAdapter, first set the SelectCommand property of the DataAdapter, then create a CommandBuilder object, and specify as an argument the DataAdapter for which the CommandBuilder will automatically generate SQL statements.

' Assumes that connection is a valid SqlConnection object
' inside of a Using block.  
Dim adapter As SqlDataAdapter = New SqlDataAdapter( _  
  "SELECT * FROM dbo.Customers", connection)  
Dim builder As SqlCommandBuilder = New SqlCommandBuilder(adapter)  
builder.QuotePrefix = "["  
builder.QuoteSuffix = "]"  
// Assumes that connection is a valid SqlConnection object  
// inside of a using block.  
SqlDataAdapter adapter = new SqlDataAdapter(  
  "SELECT * FROM dbo.Customers", connection);  
SqlCommandBuilder builder = new SqlCommandBuilder(adapter);  
builder.QuotePrefix = "[";  
builder.QuoteSuffix = "]";  

Modificar SelectCommandModifying the SelectCommand

Es posible que se inicie una excepción si modifica valor CommandText de SelectCommand después de generar automáticamente los comandos INSERT, UPDATE o DELETE.If you modify the CommandText of the SelectCommand after the INSERT, UPDATE, or DELETE commands have been automatically generated, an exception may occur. Si el valor SelectCommand.CommandText modificado contiene información del esquema que sea incoherente con el valor SelectCommand.CommandText utilizado en el momento de la generación automática de los comandos de inserción, actualización o eliminación, las futuras llamadas al método DataAdapter.Update pueden tratar de obtener acceso a columnas que ya no existen en la tabla actual a la que hace referencia SelectCommand, con lo que se iniciará una excepción.If the modified SelectCommand.CommandText contains schema information that is inconsistent with the SelectCommand.CommandText used when the insert, update, or delete commands were automatically generated, future calls to the DataAdapter.Update method may attempt to access columns that no longer exist in the current table referenced by the SelectCommand, and an exception will be thrown.

Puede actualizar la información del esquema que utiliza CommandBuilder para generar automáticamente los comandos; para ello, basta con llamar al método RefreshSchema de CommandBuilder.You can refresh the schema information used by the CommandBuilder to automatically generate commands by calling the RefreshSchema method of the CommandBuilder.

Si desea conocer el comando generado automáticamente, puede obtener una referencia a los comandos generados automáticamente mediante los métodos GetInsertCommand, GetUpdateCommand y GetDeleteCommand del objeto CommandBuilder y la comprobación de la propiedad CommandText del comando asociado.If you want to know what command was automatically generated, you can obtain a reference to the automatically generated commands by using the GetInsertCommand, GetUpdateCommand, and GetDeleteCommand methods of the CommandBuilder object and checking the CommandText property of the associated command.

En el ejemplo de código siguiente se escribe en la consola el comando de actualización generado automáticamente.The following code example writes to the console the update command that was automatically generated.

Console.WriteLine(builder.GetUpdateCommand().CommandText)  
Console.WriteLine(builder.GetUpdateCommand().CommandText);

En el siguiente ejemplo se vuelve a crear la tabla Customers en el conjunto de datos custDS.The following example recreates the Customers table in the custDS dataset. El RefreshSchema se llama al método para actualizar los comandos generados automáticamente con esta nueva información de columna.The RefreshSchema method is called to refresh the automatically generated commands with this new column information.

' Assumes an open SqlConnection and SqlDataAdapter inside of a Using block.  
adapter.SelectCommand.CommandText = _  
  "SELECT CustomerID, ContactName FROM dbo.Customers"  
builder.RefreshSchema()  
  
custDS.Tables.Remove(custDS.Tables("Customers"))  
adapter.Fill(custDS, "Customers")  
// Assumes an open SqlConnection and SqlDataAdapter inside of a using block.  
adapter.SelectCommand.CommandText =
  "SELECT CustomerID, ContactName FROM dbo.Customers";  
builder.RefreshSchema();  
  
custDS.Tables.Remove(custDS.Tables["Customers"]);  
adapter.Fill(custDS, "Customers");  

Consulte tambiénSee also