Заполнение набора данных с помощью адаптера данных DataAdapterPopulating a DataSet from a DataAdapter

ADO.NET DataSet — это резидентное представление данных, предоставляющее единообразную реляционную модель программирования независимо от источника данных.The ADO.NET DataSet is a memory-resident representation of data that provides a consistent relational programming model independent of the data source. Набор данных DataSet представляет собой полную совокупность данных, которая включает таблицы, ограничения и связи между таблицами.The DataSet represents a complete set of data that includes tables, constraints, and relationships among the tables. Набор данных DataSet является независимым от источника данных, поэтому DataSet может включать данные, локальные по отношению к приложению, а также данные из нескольких источников данных.Because the DataSet is independent of the data source, a DataSet can include data local to the application, and data from multiple data sources. Управление взаимодействием с существующими источниками данных осуществляется с помощью DataAdapter.Interaction with existing data sources is controlled through the DataAdapter.

Свойство SelectCommand объекта DataAdapter представляет собой объект Command , получающий данные из источника данных.The SelectCommand property of the DataAdapter is a Command object that retrieves data from the data source. Свойства InsertCommand, UpdateCommandи DeleteCommand , принадлежащие DataAdapter , являются объектами Command , которые управляют обновлением данных в источнике данных в соответствии с изменениями данных в 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. Эти свойства более подробно описаны в статье Обновление источников данных с помощью DataAdapter.These properties are covered in more detail in Updating Data Sources with DataAdapters.

Метод Fill объекта DataAdapter служит для заполнения набора данных DataSet результатами выполнения метода SelectCommand объекта DataAdapter.The Fill method of the DataAdapter is used to populate a DataSet with the results of the SelectCommand of the DataAdapter. МетодFill принимает в качестве аргумента подлежащий заполнению набор данных DataSet , а также объект DataTable или имя объекта DataTable , который должен быть заполнен строками, возвращенными методом 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.

Примечание

Использование DataAdapter для получения всей таблицы требует времени, особенно при наличии в ней большого числа строк.Using the DataAdapter to retrieve all of a table takes time, especially if there are many rows in the table. Это происходит вследствие того, что обращение к базе данных, обнаружение и обработка данных, а также передача данных клиенту занимают длительное время.This is because accessing the database, locating and processing the data, and then transferring the data to the client is time-consuming. Передача по запросу всей таблицы клиенту приводит также к блокировке всех строк на сервере.Pulling all of the table to the client also locks all of the rows on the server. Для повышения производительности можно использовать предложение WHERE , что позволяет значительно уменьшить количество строк, возвращаемых клиенту.To improve performance, you can use the WHERE clause to greatly reduce the number of rows returned to the client. Можно также уменьшить количество данных, возвращаемых клиенту, с помощью явно заданного списка требуемых столбцов в инструкции SELECT .You can also reduce the amount of data returned to the client by only explicitly listing required columns in the SELECT statement. Еще одним хорошим решением проблемы является получение строк в пакетах (например, содержащих несколько сотен строк одновременно), а также получение следующего пакета только после завершения обработки текущего.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.

Метод Fill неявно использует объект DataReader для возврата имен и типов столбцов, используемых для создания таблиц в DataSet, и данных для заполнения строк таблиц в 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. Таблицы и столбцы создаются только в том случае, если они еще не существуют. В противном случае метод Fill использует существующую схему DataSet .Tables and columns are only created if they do not already exist; otherwise Fill uses the existing DataSet schema. Типы столбцов создаются как типы .NET Framework в соответствии с таблицами в сопоставлении типов данных в ADO.NET.Column types are created as .NET Framework types according to the tables in Data Type Mappings in ADO.NET. Первичные ключи создаются, только если они существуют в источнике данных и свойство DataAdapter . MissingSchemaActionPrimary keys are not created unless they exist in the data source and DataAdapter.MissingSchemaAction имеет значение MissingSchemaAction . AddWithKey.is set to MissingSchemaAction.AddWithKey. Если Fill обнаруживает, что для таблицы существует первичный ключ, то данные в DataSet для строк, в которых значения столбцов первичного ключа совпадают со значениями в строках, возвращенных из источника данных, будут перезаписаны данными из источника данных.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. Если первичный ключ не найден, то данные добавляются в таблицы DataSet.If no primary key is found, the data is appended to the tables in the DataSet. Fillиспользует любые сопоставления, которые могут существовать при заполнении DataSet (см. таблицу DataAdapter DataTable и сопоставления DataColumn).Fill uses any mappings that may exist when you populate the DataSet (see DataAdapter DataTable and DataColumn Mappings).

Примечание

Если SelectCommand возвращает результаты OUTER JOIN, то DataAdapter не задает значение PrimaryKey для результирующего объекта DataTable.If the SelectCommand returns the results of an OUTER JOIN, the DataAdapter does not set a PrimaryKey value for the resulting DataTable. Чтобы обеспечить правильное обнаружение повторяющихся строк, пользователь должен определить первичный ключ, PrimaryKey .You must define the PrimaryKey yourself to make sure that duplicate rows are resolved correctly. Дополнительные сведения см. в разделе Определение первичных ключей.For more information, see Defining Primary Keys.

В следующем примере кода создается экземпляр SqlDataAdapter , в котором используется соединение SqlConnection для базы данных Northwind Microsoft SQL Server и заполняется DataTable в наборе данных DataSet списком клиентов.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. Инструкция SQL и аргументы SqlConnection , переданные в конструктор SqlDataAdapter , используются для создания свойства SelectCommand объекта SqlDataAdapter.The SQL statement and SqlConnection arguments passed to the SqlDataAdapter constructor are used to create the SelectCommand property of the SqlDataAdapter.

ПримерExample

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

Примечание

Код, показанный в данном примере, не открывает и закрывает Connectionявным образом.The code shown in this example does not explicitly open and close the Connection. Если соединение еще не открыто, то метод Fill неявно открывает Connection , которое используется DataAdapter .The Fill method implicitly opens the Connection that the DataAdapter is using if it finds that the connection is not already open. Если операция Fill открыла соединение, она также закрывает его при завершении Fill .If Fill opened the connection, it also closes the connection when Fill is finished. Это позволяет упростить код при использовании отдельной операции, такой как Fill или Update.This can simplify your code when you deal with a single operation such as a Fill or an Update. Однако при выполнении нескольких операций, требующих открытого соединения, можно повысить производительность приложения путем явного вызова метода Open объекта Connection, выполнения операций с источником данных и последующего вызова метода Close объекта 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. Необходимо сохранять соединения с источником данных лишь на такое короткое время, насколько это возможно, освобождая ресурсы для использования другими клиентскими приложениями.You should try to keep connections to the data source open as briefly as possible to free resources for use by other client applications.

Несколько результирующих наборовMultiple Result Sets

Если объект DataAdapter обнаруживает несколько результирующих наборов, то создает несколько таблиц в DataSet.If the DataAdapter encounters multiple result sets, it creates multiple tables in the DataSet. Таблицы получают добавочное имя по умолчанию TableN, для Table0 начинающееся с «Table».The tables are given an incremental default name of TableN, starting with "Table" for Table0. Если имя таблицы передается в качестве аргумента методу Fill , то таблицы получают по умолчанию имя TableNameNс последовательно увеличивающимся суффиксом, но начиная с «TableName», а не с 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.

Заполнение DataSet из нескольких адаптеров данных DataAdapterPopulating a DataSet from Multiple DataAdapters

С можно использовать DataAdapter любое количество объектов. DataSetAny number of DataAdapter objects can be used with a DataSet. Каждый объект DataAdapter может использоваться для заполнения одного или более объектов DataTable и разрешения обновлений в соответствующем источнике данных.Each DataAdapter can be used to fill one or more DataTable objects and resolve updates back to the relevant data source. ОбъектыDataRelation и Constraint могут быть добавлены к DataSet локально, что позволяет связывать данные из разнородных источников данных.DataRelation and Constraint objects can be added to the DataSet locally, which enables you to relate data from dissimilar data sources. Например, DataSet может содержать данные из базы данных Microsoft SQL Server, из базы данных IBM DB2, доступ к которой предоставляется с помощью OLE DB, и источника данных, предназначенного для получения 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. Один или несколько объектов DataAdapter могут обрабатывать соединение с каждым источником данных.One or more DataAdapter objects can handle communication to each data source.

ПримерExample

В следующем примере кода заполняется список клиентов из базы данных Northwind Microsoft SQL Server и список заказов из базы данных Northwind , который хранится в 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. Заполненные таблицы связываются с помощью DataRelation, и список клиентов отображает заказы данного клиента.The filled tables are related with a DataRelation, and the list of customers is then displayed with the orders for that customer. Дополнительные сведения об DataRelation объектах см. в разделе Добавление связей DataRelation и Навигация по связямданных.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"]);  
}  

Тип decimal SQL ServerSQL Server Decimal Type

По умолчанию DataSet данные хранятся с помощью .NET Frameworkных типов данных.By default, the DataSet stores data by using .NET Framework data types. Для большинства приложений благодаря этому появляется удобный способ представления сведений об источнике данных.For most applications, these provide a convenient representation of data source information. Однако данное представление может вызвать проблему, если типом данных в источнике данных является применяемый в SQL Server тип decimal или numeric.However, this representation may cause a problem when the data type in the data source is a SQL Server decimal or numeric data type. Тип данных decimal .NET Framework допускает не более 28 значащих цифр, а SQL Server decimal тип данных допускает 38 значащих цифр.The .NET Framework decimal data type allows a maximum of 28 significant digits, whereas the SQL Server decimal data type allows 38 significant digits. Если во время операции SqlDataAdapter Fill определяет, что точность поля decimal SQL Server больше 28 символов, текущая строка не добавляется в 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. Вместо этого происходит событие FillError , которое позволяет определить, произойдет ли потеря точности, и предпринять соответствующие действия.Instead the FillError event occurs, which enables you to determine whether a loss of precision will occur, and respond appropriately. Дополнительные сведения о событии FillError см. в разделе Обработка событий DataAdapter.For more information about the FillError event, see Handling DataAdapter Events. Для получения значения типа decimal SQL Server можно также использовать объект SqlDataReader и вызывать метод GetSqlDecimal .To get the SQL Server decimal value, you can also use a SqlDataReader object and call the GetSqlDecimal method.

В ADO.NET 2,0 введена Улучшенная поддержка в.DataSet System.Data.SqlTypesADO.NET 2.0 introduced enhanced support for System.Data.SqlTypes in the DataSet. Дополнительные сведения см. в разделе SqlTypes and the DataSet.For more information, see SqlTypes and the DataSet.

Разделы OLE DBOLE DB Chapters

Иерархические наборы строк, или разделы (тип DBTYPE_HCHAPTER в OLE DB, тип adChapter в ADO), могут использоваться для заполнения содержимого DataSet.Hierarchical rowsets, or chapters (OLE DB type DBTYPE_HCHAPTER, ADO type adChapter) can be used to fill the contents of a DataSet. Когда OleDbDataAdapter во время операции Fill обнаруживает столбец, разбитый на разделы, для этого столбца создается DataTable , данная таблица заполняется столбцами и строками из раздела.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. Таблице, созданной для разбитого на разделы столбца, присваивается имя, состоящее из имени родительской таблицы и имени разбитого на разделы столбца, в форме «ParentTableNameChapteredColumnName».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". Если в наборе данных DataSet уже содержится таблица, имя которой согласуется с именем разбитого на разделы столбца, то данными раздела заполняется текущая таблица.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. Если в существующей таблице нет столбца, совпадающего со столбцом, содержащимся в разделе, то добавляется новый столбец.If there is no column in an existing table that matches a column found in the chapter, a new column is added.

Перед заполнением таблиц в DataSet данными, содержащимися в разбитых на разделы столбцах, между родительской и дочерней таблицами иерархического набора строк создается связь путем добавления целочисленного столбца к родительской и дочерней таблицам, установки родительского столбца на автоприращение и создания DataRelation с помощью добавленных из обеих таблиц столбцов.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. Добавленной связи присваивается имя с использованием имен родительской таблицы и разбитого на разделы столбца в виде «ParentTableNameChapterColumnName».The added relation is named by using the parent table and chapter column names in the form "ParentTableNameChapterColumnName".

Обратите внимание, что связанный столбец существует только в DataSet.Note that the related column only exists in the DataSet. Дальнейшее заполнение из источника данных может вызвать добавление к таблицам новых строк вместо внесения изменений в существующие строки.Subsequent fills from the data source can cause new rows to be added to the tables instead of changes being merged into existing rows.

Обратите внимание, что при использовании перегруженного метода DataAdapter.Fill , который принимает DataTableв качестве аргумента, заполняется только эта таблица.Note also that, if you use the DataAdapter.Fill overload that takes a DataTable, only that table will be filled. Целочисленный столбец с автоприращением все еще можно добавить в таблицу, но нельзя создать или заполнить дочернюю таблицу, а также нельзя создать связь.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.

В следующем примере используется поставщик MSDataShape для создания разбитого на разделы столбца для каждого клиента из списка клиентов.The following example uses the MSDataShape Provider to generate a chapter column of orders for each customer in a list of customers. После этого DataSet заполняется данными.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");  
}  

Когда операция Fill завершена, набор данных DataSet содержит две таблицы: Customers и CustomersOrders, в которых CustomersOrders представляет столбец, разбитый на разделы.When the Fill operation is complete, the DataSet contains two tables: Customers and CustomersOrders, where CustomersOrders represents the chaptered column. Дополнительный столбец с именем Orders добавляется к таблице Customers , а дополнительный столбец с именем CustomersOrders добавляется к таблице CustomersOrders .An additional column named Orders is added to the Customers table, and an additional column named CustomersOrders is added to the CustomersOrders table. Столбец Orders в таблице Customers устанавливается на автоприращение.The Orders column in the Customers table is set to auto-increment. DataRelation, CustomersOrders, создается с помощью столбцов, которые были добавлены к таблицам с Customers в виде дочерней таблицы.A DataRelation, CustomersOrders, is created by using the columns that were added to the tables with Customers as the parent table. Следующие таблицы показывают некоторые образцы результатов.The following tables show some sample results.

TableName: ЗаказчикиTableName: 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

См. такжеSee also