Popolamento di un dataset da un oggetto DataAdapterPopulating a DataSet from a DataAdapter

L'oggetto ADO.NETADO.NET di DataSet è una rappresentazione di dati residente in memoria che fornisce un modello di programmazione relazionale coerente indipendente dall'origine dati.The ADO.NETADO.NETDataSet is a memory-resident representation of data that provides a consistent relational programming model independent of the data source. Il DataSet rappresenta un set completo di dati che include tabelle, vincoli e relazioni tra tabelle.The DataSet represents a complete set of data that includes tables, constraints, and relationships among the tables. Poiché il DataSet è indipendente dall'origine dati, un DataSet può includere dati locali dell'applicazione nonché dati di più origini dati.Because the DataSet is independent of the data source, a DataSet can include data local to the application, and data from multiple data sources. L'interazione con le origini dati esistenti è controllata tramite DataAdapter.Interaction with existing data sources is controlled through the DataAdapter.

La proprietà SelectCommand di DataAdapter è un oggetto Command che recupera i dati dall'origine dati.The SelectCommand property of the DataAdapter is a Command object that retrieves data from the data source. Le proprietà InsertCommand, UpdateCommande DeleteCommand di DataAdapter sono oggetti Command che gestiscono gli aggiornamenti ai dati nell'origine dati in base alle modifiche apportate nel 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. Queste proprietà sono descritte in dettaglio in l'aggiornamento di origini dati con DataAdapter.These properties are covered in more detail in Updating Data Sources with DataAdapters.

Il metodo Fill di DataAdapter viene usato per popolare un oggetto DataSet con i risultati dell'oggetto SelectCommand di DataAdapter.The Fill method of the DataAdapter is used to populate a DataSet with the results of the SelectCommand of the DataAdapter. Fill accetta come argomenti un oggetto DataSet da popolare e un oggetto DataTable o il nome dell'oggetto DataTable da popolare con le righe restituite da 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

L'utilizzo di DataAdapter per recuperare un'intera tabella richiede del tempo, soprattutto se la tabella contiene molte righe.Using the DataAdapter to retrieve all of a table takes time, especially if there are many rows in the table. L'accesso al database, l'individuazione e l'elaborazione dei dati e il successivo trasferimento dei dati al client tramite rete sono infatti processi lunghi.This is because accessing the database, locating and processing the data, and then transferring the data to the client is time-consuming. Se viene eseguito il pull dell'intera tabella nel client, vengono anche bloccate tutte le righe sul server.Pulling all of the table to the client also locks all of the rows on the server. Per migliorare le prestazioni, è possibile usare la clausola WHERE in modo da ridurre sensibilmente il numero di righe restituite al client.To improve performance, you can use the WHERE clause to greatly reduce the number of rows returned to the client. È anche possibile ridurre la quantità di dati restituiti al client elencando in modo esplicito solo le colonne necessarie nell'istruzione SELECT .You can also reduce the amount of data returned to the client by only explicitly listing required columns in the SELECT statement. Un'altra soluzione alternativa efficace consiste nel recuperare le righe in batch, ad esempio diverse centinaia alla volta, e recuperare il batch successivo solo quando il client ha terminato con quello corrente.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.

Nel metodo Fill viene usato in modo implicito l'oggetto DataReader per restituire i nomi e i tipi delle colonne usate per creare le tabelle nel DataSet, nonché i dati per compilare le righe delle tabelle nel 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. Le tabelle e le colonne vengono create solo se non esistono già. In caso contrario, nel metodo Fill viene usato lo schema del DataSet esistente.Tables and columns are only created if they do not already exist; otherwise Fill uses the existing DataSet schema. Tipi di colonna vengono creati come .NET Framework.NET Framework tipi in base alle tabelle in mapping dei tipi di dati in ADO.NET.Column types are created as .NET Framework.NET Framework types according to the tables in Data Type Mappings in ADO.NET. Le chiavi primarie vengono create solo se sistono nell'origine dati e DataAdapter.MissingSchemaActionPrimary keys are not created unless they exist in the data source and DataAdapter.MissingSchemaAction è impostato su MissingSchemaAction.AddWithKey.is set to MissingSchemaAction.AddWithKey. Se Fill rileva la presenza di una chiave primaria per una tabella, sovrascriverà i dati presenti nel DataSet con quelli prelevati dall'origine dati per le righe in cui i valori della colonna della chiave primaria corrispondono a quelli della riga restituita dall'origine dati.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. Se non vengono rilevate chiavi primarie , i dati vengono aggiunti alle tabelle nell'oggetto DataSet.If no primary key is found, the data is appended to the tables in the DataSet. Fill utilizza tutti i mapping esistenti quando si popola il DataSet (vedere DataAdapter, DataTable e DataColumn mapping).Fill uses any mappings that may exist when you populate the DataSet (see DataAdapter DataTable and DataColumn Mappings).

Nota

Se SelectCommand restituisce i risultati di un OUTER JOIN, mediante DataAdapter non viene impostato un valore di PrimaryKey per l'oggetto DataTablerisultante.If the SelectCommand returns the results of an OUTER JOIN, the DataAdapter does not set a PrimaryKey value for the resulting DataTable. Per assicurarsi che le righe duplicate vengano risolte correttamente, sarà necessario definire PrimaryKey in modo autonomo.You must define the PrimaryKey yourself to make sure that duplicate rows are resolved correctly. Per ulteriori informazioni, vedere la definizione di chiavi primarie.For more information, see Defining Primary Keys.

Nell'esempio di codice seguente viene creata un'istanza di un tipo SqlDataAdapter che usa un tipo SqlConnection nel database Northwind di Microsoft SQL Server e viene compilato un tipo DataTable in un DataSet con l'elenco dei clienti.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. L'istruzione SQL e gli argomenti SqlConnection passati al costruttore SqlDataAdapter vengono usati per creare la proprietà SelectCommand del tipo SqlDataAdapter.The SQL statement and SqlConnection arguments passed to the SqlDataAdapter constructor are used to create the SelectCommand property of the SqlDataAdapter.

EsempioExample

' 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

Con il codice illustrato in questo esempio, l'oggetto Connectionnon viene aperto e chiuso in modo esplicito.The code shown in this example does not explicitly open and close the Connection. Il metodo Fill apre in modo implicito l'oggetto Connection usato da DataAdapter se rileva che la connessione non è già aperta.The Fill method implicitly opens the Connection that the DataAdapter is using if it finds that the connection is not already open. Se la connessione è stata aperta da Fill , esso provvederà anche a chiuderla una volta terminato Fill .If Fill opened the connection, it also closes the connection when Fill is finished. Questa procedura consente di semplificare il codice quando si esegue una singola operazione come Fill o Update.This can simplify your code when you deal with a single operation such as a Fill or an Update. Tuttavia, se si eseguono più operazioni che richiedono una connessione aperta, per migliorare le prestazioni dell'applicazione è possibile chiamare in modo esplicito il metodo Open dell'oggetto Connection, eseguire le operazioni sull'origine dati, quindi chiamare il metodo Close dell'oggetto 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. È necessario cercare di tenere aperte le connessioni con l'origine dati per un intervallo di tempo minimo, in modo da liberare le risorse che devono essere usate da altre applicazioni client.You should try to keep connections to the data source open as briefly as possible to free resources for use by other client applications.

Più set di risultatiMultiple Result Sets

Se l'oggetto DataAdapter rileva più set di risultati, vengono create più tabelle nel DataSet.If the DataAdapter encounters multiple result sets, it creates multiple tables in the DataSet. Alle tabelle viene assegnato il nome predefinito incrementale TableN, che inizia con "Table" per Table0.The tables are given an incremental default name of TableN, starting with "Table" for Table0. Se il nome di una tabella viene passato come argomento al metodo Fill , alle tabelle viene assegnato il nome predefinito incrementale TableNameN, che inizia con "TableName" per 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.

Compilazione di un DataSet da più oggetti DataAdapterPopulating a DataSet from Multiple DataAdapters

Un numero qualsiasi di DataAdapter oggetti possono essere utilizzati con un DataSet.Any number of DataAdapter objects can be used with a DataSet. Ogni oggetto DataAdapter può essere usato per compilare uno o più oggetti DataTable e risolvere gli aggiornamenti fino all'origine dati pertinente.Each DataAdapter can be used to fill one or more DataTable objects and resolve updates back to the relevant data source. Gli oggettiDataRelation e Constraint possono essere aggiunti all'oggetto DataSet localmente, consentendo di creare relazioni tra dati provenienti da origini dati diverse.DataRelation and Constraint objects can be added to the DataSet locally, which enables you to relate data from dissimilar data sources. Un DataSet , ad esempio, può contenere dati di un database Microsoft SQL Server, un database IBM DB2 esposto tramite OLE DB e un'origine dati che crea flussi 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. Uno o più oggetti DataAdapter possono gestire le comunicazioni con ciascuna origine dati.One or more DataAdapter objects can handle communication to each data source.

EsempioExample

Nell'esempio di codice seguente vengono compilati un elenco di clienti dal database Northwind in Microsoft SQL Server e un elenco di ordini dal database Northwind archiviato in 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. Viene creata una relazione tra le tabelle compilate tramite DataRelatione viene quindi visualizzato l'elenco di clienti con i relativi ordini.The filled tables are related with a DataRelation, and the list of customers is then displayed with the orders for that customer. Per ulteriori informazioni su DataRelation degli oggetti, vedere aggiunta di oggetti DataRelation e esplorazione 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 di SQL ServerSQL Server Decimal Type

Per impostazione predefinita, il DataSet archivia i dati usando tipi di dati .NET Framework.NET Framework .By default, the DataSet stores data by using .NET Framework.NET Framework data types. Per la maggior parte delle applicazioni, questi tipi consentono di rappresentare in modo adeguato le informazioni delle origini dei dati.For most applications, these provide a convenient representation of data source information. Tuttavia, questo tipo di rappresentazione può generare un problema quando il tipo di dati nell'origine dati ha valore numeric o decimal di 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. Il tipo di dati .NET Framework.NET Framework decimal data type allows a maximum of 28 significant digits, whereas the SQL Server decimal data type allows 38 significant digits.The .NET Framework.NET Framework decimal data type allows a maximum of 28 significant digits, whereas the SQL Server decimal data type allows 38 significant digits. Se, durante un'operazione SqlDataAdapter , Fill determina che la precisione di un campo decimal di SQL Server è maggiore di 28 caratteri, la riga corrente non viene aggiunta all'oggetto 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. Viene invece generato un evento FillError , che consente di determinare se si è verificata una perdita di precisione e quindi di rispondere in modo appropriato.Instead the FillError event occurs, which enables you to determine whether a loss of precision will occur, and respond appropriately. Per ulteriori informazioni sul FillError eventi, vedere gestione di eventi DataAdapter.For more information about the FillError event, see Handling DataAdapter Events. Per ottenere il valore decimal di SQL Server, è anche possibile usare un oggetto SqlDataReader e chiamare il metodo GetSqlDecimal .To get the SQL Server decimal value, you can also use a SqlDataReader object and call the GetSqlDecimal method.

InADO.NETADO.NET 2.0 è stato introdotto un supporto migliorato per System.Data.SqlTypes nel DataSet.ADO.NETADO.NET 2.0 introduced enhanced support for System.Data.SqlTypes in the DataSet. Per altre informazioni, vedere SqlTypes and the DataSet.For more information, see SqlTypes and the DataSet.

Capitoli OLE DBOLE DB Chapters

I rowset gerarchici, o capitoli (tipo OLE DB DBTYPE_HCHAPTER, tipo ADO adChapter), possono essere usati per compilare il contenuto di un DataSet.Hierarchical rowsets, or chapters (OLE DB type DBTYPE_HCHAPTER, ADO type adChapter) can be used to fill the contents of a DataSet. Quando l'oggetto OleDbDataAdapter rileva una colonna con capitoli durante un'operazione Fill , viene creato un oggetto DataTable per la colonna e la tabella viene compilata con le colonne e le righe del capitolo.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. Il nome della tabella creata per la colonna con capitoli viene assegnato usando il nome della tabella padre e il nome della colonna con capitoli nel formato "NomeTabellaPadreNomeColonnaConCapitoli".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". Se nel DataSet esiste già una tabella con un nome corrispondente al nome della colonna con capitoli, la tabella corrente viene compilata con i dati del capitolo.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. Se in una tabella esistente non sono presenti colonne che corrispondono alla colonna rilevata nel capitolo, viene aggiunta una nuova colonna.If there is no column in an existing table that matches a column found in the chapter, a new column is added.

Prima che le tabelle nel DataSet siano compilate con i dati delle colonne con capitoli, viene creata una relazione tra le tabelle padre e figlio del rowset gerarchico aggiungendo una colonna di valori integer sia alla tabella padre che alla tabella figlio, impostando l'incremento automatico della colonna padre e creando un DataRelation con le colonne aggiunte dalle due tabelle.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. Il nome della relazione aggiunta viene assegnato usando i nomi della tabella padre e della colonna con capitoli nel formato "NomeTabellaPadreNomeColonnaConCapitoli".The added relation is named by using the parent table and chapter column names in the form "ParentTableNameChapterColumnName".

Si noti che la colonna correlata esiste solo nel DataSet.Note that the related column only exists in the DataSet. Nelle successive operazioni di inserimento dati dall'origine dati, anziché aggiornare le righe esistenti nelle tabelle in base alle modifiche, verranno aggiunte nuove righe.Subsequent fills from the data source can cause new rows to be added to the tables instead of changes being merged into existing rows.

Si noti inoltre che se si usa l'overload DataAdapter.Fill che accetta un DataTable, verrà compilata solo quella tabella.Note also that, if you use the DataAdapter.Fill overload that takes a DataTable, only that table will be filled. Una colonna di valori integer con incremento automatico verrà comunque aggiunta alla tabella, ma non verrà creata o compilata alcuna tabella figlio e non verrà creata alcuna relazione.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.

Nell'esempio seguente viene usato il provider MSDataShape per generare una colonna di ordini con capitoli per ogni cliente presente in un elenco di clienti.The following example uses the MSDataShape Provider to generate a chapter column of orders for each customer in a list of customers. Quindi, verrà compilato un DataSet con i dati.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");  
}  

Al termine dell'operazione Fill , il DataSet contiene due tabelle: Customers e CustomersOrders, dove CustomersOrders rappresenta la colonna con capitoli.When the Fill operation is complete, the DataSet contains two tables: Customers and CustomersOrders, where CustomersOrders represents the chaptered column. Alla tabella Orders viene aggiunta un'altra colonna denominata Customers e alla tabella CustomersOrders viene aggiunta un'altra colonna denominata CustomersOrders .An additional column named Orders is added to the Customers table, and an additional column named CustomersOrders is added to the CustomersOrders table. Nella colonna Orders della tabella Customers viene impostato l'incremento automatico.The Orders column in the Customers table is set to auto-increment. Viene creato un oggetto DataRelation, CustomersOrders, usando le colonne aggiunte alle tabelle con Customers come tabella padre.A DataRelation, CustomersOrders, is created by using the columns that were added to the tables with Customers as the parent table. Nelle tabelle seguenti sono illustrati alcuni risultati di esempio.The following tables show some sample results.

TableName: CustomersTableName: Customers

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

TableName: CustomersOrdersTableName: CustomersOrders

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

Vedere ancheSee Also

DataAdapter e DataReaderDataAdapters and DataReaders
Mapping dei tipi di dati in ADO.NETData Type Mappings in ADO.NET
Modifica di dati con un oggetto DbDataAdapterModifying Data with a DbDataAdapter
MARS (Multiple Active Result Set)Multiple Active Result Sets (MARS)
Provider gestiti ADO.NET e Centro per sviluppatori di set di datiADO.NET Managed Providers and DataSet Developer Center