Condividi tramite


Riempimento di un DataSet da un DataAdapter

Il ADO.NET DataSet è una rappresentazione residente in memoria dei dati che fornisce un modello di programmazione relazionale coerente indipendentemente dall'origine dati. Rappresenta DataSet un set completo di dati che include tabelle, vincoli e relazioni tra le tabelle. Poiché il DataSet è indipendente dall'origine dati, un DataSet può includere dati locali all'applicazione e dati da più origini dati. L'interazione con le origini dati esistenti viene controllata tramite .DataAdapter

La SelectCommand proprietà di DataAdapter è un Command oggetto che recupera i dati dalla fonte dati. Le proprietà InsertCommand, UpdateCommand e DeleteCommand di DataAdapter sono Command oggetti che gestiscono gli aggiornamenti ai dati nell'origine dati secondo le modifiche effettuate sui dati in DataSet. Queste proprietà sono descritte in modo più dettagliato in Aggiornamento delle origini dati con DataAdapter.

Il metodo Fill di DataAdapter viene utilizzato per popolare un DataSet con i risultati di SelectCommand di DataAdapter. Fill accetta come argomenti un DataSet oggetto da popolare e un DataTable oggetto oppure il nome dell'oggetto DataTable da riempire con le righe restituite da SelectCommand.

Annotazioni

L'utilizzo di DataAdapter per recuperare tutte le tabelle richiede tempo, soprattutto se nella tabella sono presenti molte righe. Ciò è dovuto al fatto che l'accesso al database, l'individuazione e l'elaborazione dei dati e quindi il trasferimento dei dati al client richiede molto tempo. Trasferire tutta la tabella al client blocca anche tutte le righe sul server. Per migliorare le prestazioni, è possibile usare la WHERE clausola per ridurre notevolmente il numero di righe restituite al client. È anche possibile ridurre la quantità di dati restituiti al client elencando in modo esplicito le colonne richieste nell'istruzione SELECT . Un'altra buona soluzione consiste nel recuperare le righe in batch (ad esempio diverse centinaia di righe alla volta) e recuperare il batch successivo solo al termine del batch corrente.

Il Fill metodo usa l'oggetto DataReader in modo implicito per restituire i nomi e i tipi di colonna utilizzati per creare le tabelle in DataSete i dati per popolare le righe delle tabelle in DataSet. Le tabelle e le colonne vengono create solo se non esistono già; in caso contrario Fill , usa lo schema esistente DataSet . I tipi di colonna vengono creati come tipi .NET Framework in base alle tabelle nelle mappature dei tipi di dati in ADO.NET. Le chiavi primarie non vengono create a meno che non esistano nell'origine dati e DataAdapter.MissingSchemaAction è impostato su MissingSchemaAction.AddWithKey. Se Fill rileva che esiste una chiave primaria per una tabella, sovrascriverà i dati nell'oggetto DataSet con i dati dell'origine dati per le righe in cui i valori della colonna chiave primaria corrispondono a quelli della riga restituita dall'origine dati. Se non viene trovata alcuna chiave primaria, i dati vengono aggiunti alle tabelle di DataSet. Fill usa tutti i mapping che possono esistere quando si popola l'oggetto DataSet (vedere DataAdapter DataTable e Mapping DataColumn).

Annotazioni

Se SelectCommand restituisce i risultati di un OUTER JOIN, DataAdapter non imposta un valore PrimaryKey per l'elemento risultante DataTable. È necessario definire manualmente PrimaryKey per assicurarsi che le righe duplicate vengano risolte correttamente. Per altre informazioni, vedere Definizione delle chiavi primarie.

Nell'esempio di codice seguente viene creata un'istanza di SqlDataAdapter che utilizza SqlConnection per il database Northwind Microsoft SQL Server e popola un DataTable con l'elenco dei clienti in un DataSet. L'istruzione SQL e SqlConnection argomenti passati al costruttore SqlDataAdapter vengono utilizzati per creare la proprietà SelectCommand di SqlDataAdapter.

Esempio

' 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");  

Annotazioni

Il codice illustrato in questo esempio non apre e chiude in modo esplicito il Connection. Il metodo Fill apre in modo implicito l'oggetto Connection che il DataAdapter utilizza se rileva che la connessione non è già aperta. Quando Fill apre la connessione, chiude anche la connessione quando Fill è completato. Ciò consente di semplificare il codice quando si gestisce una singola operazione, come Fill o Update. Tuttavia, se si eseguono più operazioni che richiedono una connessione aperta, è possibile migliorare le prestazioni dell'applicazione chiamando in modo esplicito il Open metodo di Connection, eseguendo le operazioni sull'origine dati e quindi chiamando il Close metodo dell'oggetto Connection. È consigliabile provare a mantenere aperte le connessioni all'origine dati per il minor tempo possibile per liberare risorse da utilizzare da parte di altre applicazioni client.

Più set di risultati

Se il DataAdapter incontra più set di risultati, crea più tabelle in DataSet. Alle tabelle viene assegnato un nome predefinito incrementale di TableN, a partire da "Table" per Table0. Se un nome di tabella viene passato come argomento al Fill metodo , alle tabelle viene assegnato un nome predefinito incrementale di TableNameN, a partire da "TableName" per TableName0.

Popolamento di un set di dati da più dataadapter

È possibile usare un numero qualsiasi di DataAdapter oggetti con un oggetto DataSet. Ognuno di essi DataAdapter può essere usato per riempire uno o più DataTable oggetti e risolvere gli aggiornamenti nell'origine dati pertinente. DataRelation e Constraint oggetti possono essere aggiunti all'oggetto DataSet localmente, permettendo di correlare i dati da origini dati diverse. Ad esempio, un DataSet può contenere dati da un database di Microsoft SQL Server, un database IBM DB2 esposto tramite OLE DB e un'origine dati che trasmette XML. Uno o più DataAdapter oggetti possono gestire la comunicazione con ogni origine dati.

Esempio

Nell'esempio di codice seguente viene popolato un elenco di clienti dal Northwind database in Microsoft SQL Server e un elenco di ordini dal Northwind database archiviato in Microsoft Access 2000. Le tabelle compilate sono correlate con un DataRelation e l'elenco dei clienti viene quindi visualizzato insieme agli ordini che li riguardano. Per altre informazioni sugli DataRelation oggetti, vedere Aggiunta di oggetti DataRelations e Esplorazione di 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 decimale di SQL Server

Per impostazione predefinita, DataSet archivia i dati utilizzando i tipi di dati del .NET Framework. Per la maggior parte delle applicazioni, questi forniscono una rappresentazione pratica delle informazioni sull'origine dati. Tuttavia, questa rappresentazione può causare un problema quando il tipo di dati nell'origine dati è un tipo di dati decimale o numerico di SQL Server. Il tipo di dati .NET Framework decimal consente un massimo di 28 cifre significative, mentre il tipo di dati di SQL Server decimal consente 38 cifre significative. Se SqlDataAdapter stabilisce durante un'operazione Fill che la precisione di un campo SQL Server decimal è maggiore di 28 caratteri, la riga corrente non viene aggiunta al DataTable. L'evento FillError si verifica invece, che consente di determinare se si verificherà una perdita di precisione e rispondere in modo appropriato. Per altre informazioni sull'evento FillError , vedere Gestione degli eventi DataAdapter. Per ottenere il valore di SQL Server decimal , è anche possibile usare un SqlDataReader oggetto e chiamare il GetSqlDecimal metodo .

ADO.NET 2.0 ha introdotto il supporto avanzato per System.Data.SqlTypes in DataSet. Per altre informazioni, vedere SqlTypes e DataSet.

Capitoli OLE DB

I set di righe gerarchici o i capitoli (tipo DBTYPE_HCHAPTEROLE DB , tipo adChapterADO ) possono essere usati per riempire il contenuto di un oggetto DataSet. Quando il OleDbDataAdapter rileva una colonna capitolata durante un'operazione Fill, viene creato un DataTable per tale colonna e questa tabella viene riempita con le colonne e le righe del capitolo. La tabella creata per la colonna con capitoli viene denominata usando sia il nome della tabella padre che il nome della colonna con capitoli nel formato "ParentTableNameChapteredColumnName". Se esiste già una tabella in DataSet che corrisponde al nome della colonna con capitoli, la tabella corrente viene compilata con i dati del capitolo. Se non è presente alcuna colonna in una tabella esistente che corrisponde a una colonna trovata nel capitolo, viene aggiunta una nuova colonna.

Prima che le tabelle nell'oggetto DataSet vengano riempite con i dati nelle colonne con capitoli, viene creata una relazione tra le tabelle padre e figlio del set di righe gerarchico aggiungendo una colonna integer alla tabella padre e figlio, impostando la colonna padre su incremento automatico e creando un DataRelation oggetto utilizzando le colonne aggiunte da entrambe le tabelle. La relazione aggiunta viene denominata utilizzando i nomi delle colonne della tabella padre e del capitolo nel formato "ParentTableNameChapterColumnName".

Si noti che la colonna correlata esiste solo in DataSet. I riempimenti successivi dall'origine dati possono causare l'aggiunta di nuove righe alle tabelle invece di fondere le modifiche nelle righe esistenti.

Si noti che, se si utilizza l'overload DataAdapter.Fill che prende un DataTable, verrà riempita solo quella tabella. Alla tabella verrà comunque aggiunta una colonna integer con incremento automatico, ma non verrà creata o compilata alcuna tabella figlio e non verrà creata alcuna relazione.

Nell'esempio seguente viene usato il provider MSDataShape per generare una colonna capitolo di ordini per ogni cliente in un elenco di clienti. Un DataSet viene quindi popolato con i dati.

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 , DataSet contiene due tabelle: Customers e CustomersOrders, dove CustomersOrders rappresenta la colonna con capitoli. Viene aggiunta una colonna aggiuntiva denominata Orders alla Customers tabella e viene aggiunta una colonna aggiuntiva denominata CustomersOrders alla CustomersOrders tabella. La Orders colonna nella Customers tabella è impostata su incremento automatico. Un DataRelationoggetto , CustomersOrdersviene creato usando le colonne aggiunte alle tabelle con Customers come tabella padre. Le tabelle seguenti mostrano alcuni risultati di esempio.

TableName: Clienti

ID Cliente NomeAzienda Ordini
ALFKI Alfreds Futterkiste 0
ANATR Ana Trujillo Panini e gelati 1

TableName: OrdiniClienti

ID Cliente OrderID OrdiniClienti
ALFKI 10643 0
ALFKI 10692 0
ANATR 10308 1
ANATR 10625 1

Vedere anche