Rellenar un conjunto de datos desde un objeto DataAdapterPopulating a DataSet from a DataAdapter

ADO.NET DataSet es una representación residente en memoria de los datos que proporciona un modelo de programación relacional coherente independiente del origen de datos.The ADO.NET DataSet is a memory-resident representation of data that provides a consistent relational programming model independent of the data source. DataSet representa un conjunto completo de datos que incluye tablas, restricciones y relaciones entre las tablas.The DataSet represents a complete set of data that includes tables, constraints, and relationships among the tables. Dado que DataSet es independiente del origen de datos, DataSet puede incluir datos locales de la aplicación y datos de otros muchos orígenes.Because the DataSet is independent of the data source, a DataSet can include data local to the application, and data from multiple data sources. La interacción con los orígenes de datos existentes se controla mediante el DataAdapter.Interaction with existing data sources is controlled through the DataAdapter.

La propiedad SelectCommand de DataAdapter es un objeto Command que recupera datos del origen de datos.The SelectCommand property of the DataAdapter is a Command object that retrieves data from the data source. Las propiedades InsertCommand, UpdateCommandy DeleteCommand de DataAdapter son objetos Command que permiten administrar las actualizaciones de los datos en el origen de datos para reflejar las modificaciones efectuadas en los datos de DataSet.The InsertCommand, UpdateCommand, and DeleteCommand properties of the DataAdapter are Command objects that manage updates to the data in the data source according to modifications made to the data in the DataSet. Estas propiedades se describen con más detalle en Actualizar orígenes de datos con DataAdapters.These properties are covered in more detail in Updating Data Sources with DataAdapters.

El método Fill de DataAdapter se usa para rellenar un objeto DataSet con los resultados del elemento SelectCommand de DataAdapter.The Fill method of the DataAdapter is used to populate a DataSet with the results of the SelectCommand of the DataAdapter. Fill toma como argumentos un elemento DataSet que se debe rellenar y un objeto DataTable o el nombre del objeto DataTable que se debe rellenar con las filas que devuelve SelectCommand.Fill takes as its arguments a DataSet to be populated, and a DataTable object, or the name of the DataTable to be filled with the rows returned from the SelectCommand.

Nota

El uso de DataAdapter para recuperar la totalidad de una tabla lleva tiempo, en especial si la tabla incluye un gran número de filas.Using the DataAdapter to retrieve all of a table takes time, especially if there are many rows in the table. Esto se debe a que el acceso a la base de datos, la localización y el procesamiento de los datos, y la posterior transferencia de los mismos al cliente son procesos largos.This is because accessing the database, locating and processing the data, and then transferring the data to the client is time-consuming. La extracción de la tabla completa al cliente también bloquea todas las filas en el servidor.Pulling all of the table to the client also locks all of the rows on the server. Para mejorar el rendimiento, puede usar la cláusula WHERE para reducir en gran medida el número de filas que se devuelven al cliente.To improve performance, you can use the WHERE clause to greatly reduce the number of rows returned to the client. También puede reducir la cantidad de datos que se devuelven al cliente si enumera de forma explícita las columnas necesarias en la instrucción SELECT .You can also reduce the amount of data returned to the client by only explicitly listing required columns in the SELECT statement. Otra solución consiste en recuperar las filas por lotes (por ejemplo varios cientos de filas de una vez) y recuperar solo el siguiente lote cuando el cliente haya finalizado con el lote actual.Another good workaround is to retrieve the rows in batches (such as several hundred rows at a time) and only retrieve the next batch when the client is finished with the current batch.

El método Fill utiliza el objeto DataReader de forma implícita para devolver los nombres y tipos de columna que se usan para crear las tablas de DataSet, y los datos para rellenar las filas de las tablas en DataSet.The Fill method uses the DataReader object implicitly to return the column names and types that are used to create the tables in the DataSet, and the data to populate the rows of the tables in the DataSet. Las tablas y columnas solo se crean cuando no existen; en caso contrario, Fill utiliza el esquema existente de DataSet .Tables and columns are only created if they do not already exist; otherwise Fill uses the existing DataSet schema. Los tipos de columna se crean como tipos de .NET Framework de acuerdo con las tablas de las asignaciones de tipos de datos en ADO.net.Column types are created as .NET Framework types according to the tables in Data Type Mappings in ADO.NET. Las claves principales no se crean a menos que existan en el origen de datos y DataAdapter .MissingSchemaActionPrimary keys are not created unless they exist in the data source and DataAdapter.MissingSchemaAction está establecido en MissingSchemaAction . AddWithKey .is set to MissingSchemaAction.AddWithKey. Si el método Fill encuentra que una tabla tiene una clave principal, sobrescribe los datos de DataSet con los del origen de datos en las filas donde los valores de columna de clave principal coinciden con los de la fila que devuelve el origen de datos.If Fill finds that a primary key exists for a table, it will overwrite data in the DataSet with data from the data source for rows where the primary key column values match those of the row returned from the data source. Si no se detecta ninguna clave principal, los datos se agregan a las tablas de DataSet.If no primary key is found, the data is appended to the tables in the DataSet. Fillutiliza las asignaciones que pueden existir al rellenar DataSet (vea las asignaciones DataTable y DataColumn de DataAdapter).Fill uses any mappings that may exist when you populate the DataSet (see DataAdapter DataTable and DataColumn Mappings).

Nota

Si SelectCommand devuelve los resultados de OUTER JOIN, DataAdapter no establece un valor PrimaryKey para el objeto DataTableresultante.If the SelectCommand returns the results of an OUTER JOIN, the DataAdapter does not set a PrimaryKey value for the resulting DataTable. Debe definir PrimaryKey para asegurarse de que las filas duplicadas se resuelven correctamente.You must define the PrimaryKey yourself to make sure that duplicate rows are resolved correctly. Para obtener más información, vea definir claves principales.For more information, see Defining Primary Keys.

En el ejemplo de código siguiente se crea una instancia de SqlDataAdapter que utiliza un objeto SqlConnection a la base de datos Northwind de Microsoft SQL Server y se rellena un objeto DataTable en un DataSet con la lista de clientes.The following code example creates an instance of a SqlDataAdapter that uses a SqlConnection to the Microsoft SQL Server Northwind database and populates a DataTable in a DataSet with the list of customers. La instrucción SQL y los argumentos SqlConnection pasados al constructor SqlDataAdapter se utilizan para crear la propiedad SelectCommand del SqlDataAdapter.The SQL statement and SqlConnection arguments passed to the SqlDataAdapter constructor are used to create the SelectCommand property of the SqlDataAdapter.

EjemploExample

' Assumes that connection is a valid SqlConnection object.  
Dim queryString As String = _  
  "SELECT CustomerID, CompanyName FROM dbo.Customers"  
Dim adapter As SqlDataAdapter = New SqlDataAdapter( _  
  queryString, connection)  
  
Dim customers As DataSet = New DataSet  
adapter.Fill(customers, "Customers")  
// Assumes that connection is a valid SqlConnection object.  
string queryString =
  "SELECT CustomerID, CompanyName FROM dbo.Customers";  
SqlDataAdapter adapter = new SqlDataAdapter(queryString, connection);  
  
DataSet customers = new DataSet();  
adapter.Fill(customers, "Customers");  

Nota

El código que se muestra en este ejemplo no abre ni cierra explícitamente el objeto Connection.The code shown in this example does not explicitly open and close the Connection. El método Fill abre de forma implícita el objeto Connection que DataAdapter utiliza cuando encuentra que la conexión no está abierta todavía.The Fill method implicitly opens the Connection that the DataAdapter is using if it finds that the connection is not already open. Si el método Fill ha abierto la conexión, también la cierra cuando el método Fill deja de utilizarla.If Fill opened the connection, it also closes the connection when Fill is finished. Este hecho simplifica el código cuando se trabaja con una operación única, como Fill o Update.This can simplify your code when you deal with a single operation such as a Fill or an Update. Sin embargo, en el caso de que se estén realizando varias operaciones que necesiten tener abierta una conexión, se puede mejorar el rendimiento de la aplicación llamando explícitamente al método Open de Connection, realizando las operaciones en el origen de datos y, finalmente, llamando al método Close de Connection.However, if you are performing multiple operations that require an open connection, you can improve the performance of your application by explicitly calling the Open method of the Connection, performing the operations against the data source, and then calling the Close method of the Connection. Es conveniente mantener abiertas las conexiones con el origen de datos el menor tiempo posible para liberar recursos, de manera que estén disponibles para otras aplicaciones cliente.You should try to keep connections to the data source open as briefly as possible to free resources for use by other client applications.

Varios conjuntos de resultadosMultiple Result Sets

Si DataAdapter encuentra varios conjuntos de resultados, crea varias tablas en DataSet.If the DataAdapter encounters multiple result sets, it creates multiple tables in the DataSet. Las tablas reciben de forma predeterminada el nombre secuencial TableN, comenzando por "Table" que representa Table0.The tables are given an incremental default name of TableN, starting with "Table" for Table0. Si se pasa un nombre de tabla como argumento al método Fill , las tablas reciben de forma predeterminada el nombre secuencial TableNameN, comenzando por "TableName" que representa TableName0.If a table name is passed as an argument to the Fill method, the tables are given an incremental default name of TableNameN, starting with "TableName" for TableName0.

Llenar un DataSet desde múltiples DataAdapterPopulating a DataSet from Multiple DataAdapters

DataAdapterSe puede usar cualquier número de objetos con DataSet .Any number of DataAdapter objects can be used with a DataSet. Cada DataAdapter se puede usar para rellenar uno o varios objetos DataTable y resolver de nuevo las actualizaciones en el origen de datos correspondiente.Each DataAdapter can be used to fill one or more DataTable objects and resolve updates back to the relevant data source. Se pueden agregar objetosDataRelation y Constraint a DataSet localmente, lo que permite relacionar datos procedentes de varios orígenes distintos.DataRelation and Constraint objects can be added to the DataSet locally, which enables you to relate data from dissimilar data sources. Por ejemplo, un DataSet puede contener datos de una base de datos de Microsoft SQL Server, una base de datos de IBM DB2 expuesta mediante OLE DB y un origen de datos que genera secuencias XML.For example, a DataSet can contain data from a Microsoft SQL Server database, an IBM DB2 database exposed through OLE DB, and a data source that streams XML. La comunicación con cada origen de datos se puede controlar usando uno o varios objetos DataAdapter .One or more DataAdapter objects can handle communication to each data source.

EjemploExample

En el ejemplo de código siguiente se rellena una lista de clientes a partir de la base de datos Northwind almacenada en Microsoft SQL Server, y una lista de pedidos a partir de la base de datos Northwind almacenada en Microsoft Access 2000.The following code example populates a list of customers from the Northwind database on Microsoft SQL Server, and a list of orders from the Northwind database stored in Microsoft Access 2000. Las tablas rellenas se relacionan entre sí mediante DataRelation, con lo que se puede mostrar una lista de clientes con los pedidos que ha realizado cada uno.The filled tables are related with a DataRelation, and the list of customers is then displayed with the orders for that customer. Para obtener más información acerca de los DataRelation objetos, vea Agregar DataRelations y navegar por DataRelations.For more information about DataRelation objects, see Adding DataRelations and Navigating DataRelations.

' Assumes that customerConnection is a valid SqlConnection object.  
' Assumes that orderConnection is a valid OleDbConnection object.  
Dim custAdapter As SqlDataAdapter = New SqlDataAdapter( _  
  "SELECT * FROM dbo.Customers", customerConnection)  
  
Dim ordAdapter As OleDbDataAdapter = New OleDbDataAdapter( _  
  "SELECT * FROM Orders", orderConnection)  
  
Dim customerOrders As DataSet = New DataSet()  
custAdapter.Fill(customerOrders, "Customers")  
ordAdapter.Fill(customerOrders, "Orders")  
  
Dim relation As DataRelation = _  
  customerOrders.Relations.Add("CustOrders", _  
  customerOrders.Tables("Customers").Columns("CustomerID"), _
  customerOrders.Tables("Orders").Columns("CustomerID"))  
  
Dim pRow, cRow As DataRow  
For Each pRow In customerOrders.Tables("Customers").Rows  
  Console.WriteLine(pRow("CustomerID").ToString())  
  
  For Each cRow In pRow.GetChildRows(relation)  
    Console.WriteLine(vbTab & cRow("OrderID").ToString())  
  Next  
Next  
// Assumes that customerConnection is a valid SqlConnection object.  
// Assumes that orderConnection is a valid OleDbConnection object.  
SqlDataAdapter custAdapter = new SqlDataAdapter(  
  "SELECT * FROM dbo.Customers", customerConnection);  
OleDbDataAdapter ordAdapter = new OleDbDataAdapter(  
  "SELECT * FROM Orders", orderConnection);  
  
DataSet customerOrders = new DataSet();  
  
custAdapter.Fill(customerOrders, "Customers");  
ordAdapter.Fill(customerOrders, "Orders");  
  
DataRelation relation = customerOrders.Relations.Add("CustOrders",  
  customerOrders.Tables["Customers"].Columns["CustomerID"],  
  customerOrders.Tables["Orders"].Columns["CustomerID"]);  
  
foreach (DataRow pRow in customerOrders.Tables["Customers"].Rows)  
{  
  Console.WriteLine(pRow["CustomerID"]);  
   foreach (DataRow cRow in pRow.GetChildRows(relation))  
    Console.WriteLine("\t" + cRow["OrderID"]);  
}  

Tipo decimal de SQL ServerSQL Server Decimal Type

De forma predeterminada, DataSet almacena los datos mediante .NET Framework tipos de datos.By default, the DataSet stores data by using .NET Framework data types. En la mayor parte de las aplicaciones, estos tipos proporcionan una representación adecuada de la información del origen de datos.For most applications, these provide a convenient representation of data source information. Sin embargo, esa representación puede ocasionar problemas cuando el tipo de datos del origen de datos es decimal o numérico de SQL Server.However, this representation may cause a problem when the data type in the data source is a SQL Server decimal or numeric data type. El decimal tipo de datos .NET Framework permite un máximo de 28 dígitos significativos, mientras que el decimal tipo de datos SQL Server permite 38 dígitos significativos.The .NET Framework decimal data type allows a maximum of 28 significant digits, whereas the SQL Server decimal data type allows 38 significant digits. Si SqlDataAdapter determina durante una operación Fill que la precisión de un campo decimal de SQL Server es superior a 28 caracteres, la fila actual no se agrega a DataTable.If the SqlDataAdapter determines during a Fill operation that the precision of a SQL Server decimal field is larger than 28 characters, the current row is not added to the DataTable. En su lugar, se produce el evento FillError que permite determinar si se va a producir o no una pérdida de precisión y tomar las medidas adecuadas.Instead the FillError event occurs, which enables you to determine whether a loss of precision will occur, and respond appropriately. Para obtener más información sobre el FillError evento, vea controlar eventos DataAdapter.For more information about the FillError event, see Handling DataAdapter Events. Para obtener el valor decimal de SQL Server, también se puede utilizar un objeto SqlDataReader y llamar al método GetSqlDecimal .To get the SQL Server decimal value, you can also use a SqlDataReader object and call the GetSqlDecimal method.

ADO.NET 2,0 presentó compatibilidad mejorada con System.Data.SqlTypes en DataSet .ADO.NET 2.0 introduced enhanced support for System.Data.SqlTypes in the DataSet. Para obtener más información, consulta SqlTypes and the DataSet.For more information, see SqlTypes and the DataSet.

Capítulos de OLE DBOLE DB Chapters

Se pueden usar conjuntos jerárquicos de filas, o capítulos (tipo DBTYPE_HCHAPTERde OLE DB y tipo adChapterde ADO), para rellenar el contenido de DataSet.Hierarchical rowsets, or chapters (OLE DB type DBTYPE_HCHAPTER, ADO type adChapter) can be used to fill the contents of a DataSet. Cuando OleDbDataAdapter encuentra una columna que tiene un capítulo durante una operación Fill , se crea un objeto DataTable para dicha columna y la tabla se rellena con las columnas y filas del capítulo.When the OleDbDataAdapter encounters a chaptered column during a Fill operation, a DataTable is created for the chaptered column, and that table is filled with the columns and rows from the chapter. Para asignar un nombre a la tabla creada para la columna con capítulo se usa tanto el nombre de la tabla primaria como el de la columna con capítulo. El formato del nombre es "nombreDeTablaPrimariaNombreDeColumnaConCapítulo".The table created for the chaptered column is named by using both the parent table name and the chaptered column name in the form "ParentTableNameChapteredColumnName". Si ya existe una tabla en DataSet que tenga el nombre de la columna con capítulo, la tabla actual se rellena con los datos del capítulo.If a table already exists in the DataSet that matches the name of the chaptered column, the current table is filled with the chapter data. Si ninguna de las columnas de la tabla existente coincide con una de las columnas del capítulo, se agrega una nueva columna a la tabla.If there is no column in an existing table that matches a column found in the chapter, a new column is added.

Antes de que las tablas de DataSet se rellenen con los datos de las columnas con capítulos, se crea una relación entre las tablas primaria y secundaria del conjunto jerárquico de filas; para ello, se agrega una columna de tipo entero a las tablas primaria y secundaria, se establece el valor de incremento automático para la columna de la tabla primaria y se crea un objeto DataRelation usando las columnas agregadas de ambas tablas.Before the tables in the DataSet are filled with the data in the chaptered columns, a relation is created between the parent and child tables of the hierarchical rowset by adding an integer column to both the parent and child table, setting the parent column to auto-increment, and creating a DataRelation using the added columns from both tables. Para asignar un nombre a la relación se utilizan los nombres de la tabla primaria y de la columna con capítulo. El formato es "nombreDeTablaPrimariaNombreDeColumnaConCapítulo".The added relation is named by using the parent table and chapter column names in the form "ParentTableNameChapterColumnName".

Tenga en cuenta que la columna relacionada solo existe en DataSet.Note that the related column only exists in the DataSet. Las operaciones de relleno que se realicen posteriormente desde el origen de datos pueden provocar que se agreguen nuevas filas a las tablas en lugar de que se introduzcan los cambios en las filas existentes.Subsequent fills from the data source can cause new rows to be added to the tables instead of changes being merged into existing rows.

Tenga en cuenta además que, si se utiliza una sobrecarga de DataAdapter.Fill que acepte un objeto DataTable, solo se rellanará esa tabla.Note also that, if you use the DataAdapter.Fill overload that takes a DataTable, only that table will be filled. En este caso también se agrega a la tabla una columna de tipo entero y con incremento automático, aunque no se crea ni rellena ninguna tabla secundaria, ni se crea ninguna relación.An auto-incrementing integer column will still be added to the table, but no child table will be created or filled, and no relation will be created.

En el ejemplo siguiente se utiliza el proveedor MSDataShape para generar un capítulo con la columna de pedidos realizados por cada uno de los clientes de una lista.The following example uses the MSDataShape Provider to generate a chapter column of orders for each customer in a list of customers. A continuación, se rellena un DataSet con los datos.A DataSet is then filled with the data.

Using connection As OleDbConnection = New OleDbConnection( _  
  "Provider=MSDataShape;Data Provider=SQLOLEDB;" & _  
  "Data Source=(local);Integrated " & _  
  "Security=SSPI;Initial Catalog=northwind")  
  
Dim adapter As OleDbDataAdapter = New OleDbDataAdapter( _  
  "SHAPE {SELECT CustomerID, CompanyName FROM Customers} " & _  
  "APPEND ({SELECT CustomerID, OrderID FROM Orders} AS Orders " & _  
  "RELATE CustomerID TO CustomerID)", connection)  
  
Dim customers As DataSet = New DataSet()  
  
adapter.Fill(customers, "Customers")  
End Using  
using (OleDbConnection connection = new OleDbConnection("Provider=MSDataShape;Data Provider=SQLOLEDB;" +  
  "Data Source=(local);Integrated Security=SSPI;Initial Catalog=northwind"))  
{  
OleDbDataAdapter adapter = new OleDbDataAdapter("SHAPE {SELECT CustomerID, CompanyName FROM Customers} " +  
  "APPEND ({SELECT CustomerID, OrderID FROM Orders} AS Orders " +  
  "RELATE CustomerID TO CustomerID)", connection);  
  
DataSet customers = new DataSet();  
adapter.Fill(customers, "Customers");  
}  

Una vez completada la operación Fill , DataSet contiene dos tablas: Customers y CustomersOrders, donde CustomersOrders representa la columna con capítulo.When the Fill operation is complete, the DataSet contains two tables: Customers and CustomersOrders, where CustomersOrders represents the chaptered column. Se agrega una columna adicional denominada Orders a la tabla Customers , y una columna adicional denominada CustomersOrders a la tabla CustomersOrders .An additional column named Orders is added to the Customers table, and an additional column named CustomersOrders is added to the CustomersOrders table. Se establece el valor de incremento automático para la columna Orders de la tabla Customers .The Orders column in the Customers table is set to auto-increment. Se crea también una relación DataRelation, CustomersOrders, utilizando las columnas que se han agregado a las tablas, siendo Customers la tabla primaria.A DataRelation, CustomersOrders, is created by using the columns that were added to the tables with Customers as the parent table. Las siguientes tablas muestran algunos ejemplos de los resultados.The following tables show some sample results.

Nombre de tabla: CustomersTableName: Customers

CustomerIDCustomerID CompanyNameCompanyName OrdersOrders
ALFKIALFKI Alfreds FutterkisteAlfreds Futterkiste 00
ANATRANATR Ana Trujillo Emparedados y heladosAna Trujillo Emparedados y helados 11

Nombre de tabla: CustomersOrdersTableName: CustomersOrders

CustomerIDCustomerID OrderIDOrderID CustomersOrdersCustomersOrders
ALFKIALFKI 1064310643 00
ALFKIALFKI 1069210692 00
ANATRANATR 1030810308 11
ANATRANATR 1062510625 11

Consulte tambiénSee also