Применение ADO.NET-объекта DataSet
Объект DataAdapter извлекает данные из источника и заполняет объекты DataTable внутри DataSet. Для выполнения запросов к базе данных объекту DataAdapter требуется объект Connection.
Если запрос возвращает несколько наборов результатов, DataSet сохраняет каждый из них в отдельной таблице. Между таблицами может существовать отношение (relationship).
Отношение между таблицами
Как только вы связываете две таблицы в DataSet через отношение (с помощью объекта DataRelation), навигация по ним упрощается. Кроме того, связывание облегчает выборку всех дочерних строк (объектов DataRow) одной таблицы для родительской строки в другой таблице (объекте DataTable). Для выборки дочерних строк используется перегруженный метод GetChildRows объекта DataRow.
Отношения устанавливаются созданием объекта DataRelation, который сопоставляет строки одной таблицы со строками другой. Эти отношения хранятся в объекте DataRelationCollection, который содержится в объекте DataSet.
Связывать таблицы в объекте DataSet не обязательно. Их можно оставить несвязанными. Однако, если между двумя таблицами существуют какие-либо отношения, например через внешний ключ (foreign key relation), то связывание таблиц упростит доступ к дочерним строкам в одном объекте DataTable из родительской строки в другом объекте DataTable.
В следующем примере кода демонстрируется выборка заказов и их позиций (order details) из таблиц Orders и OrderDetails. Объект DataSet содержит таблицы Orders и Details, соответствующие таблицам в базе данных. Связью между двумя таблицами служит столбец ’OrderId’, присутствующий в обоих объектах DataTables.
Dim sqlDA As SqlDataAdapter
Dim hierDS As DataSet
Dim orderRow As DataRow
Dim detailRow As DataRow
Dim detailRows() As DataRow
Dim i As Integer
Try
' Создать новый объект DataAdapter
sqlDA = New SqlDataAdapter()
' Создать новый объект DataSet
hierDS = New DataSet()
' Задать сопоставления таблиц
sqlDA.TableMappings.Add("Orders", "Orders")
sqlDA.TableMappings.Add("Orders1", "OrderDetails")
With sqlDA
' Добавить объект SelectCommand
.SelectCommand = New SqlCommand()
' Указать команду объекта SelectCommand
With .SelectCommand
.CommandType = CommandType.StoredProcedure
.CommandText = "GetOrders"
.Connection = New SqlConnection(myConnString)
End With
' Заполнить DataSet возвращаемыми данными
.Fill(hierDS, "Orders")
End With
Так как до вызова метода Fill в объекте DataSet нет таблиц, объект SQLDataAdapter автоматически создает таблицы для DataSet и заполняет их возвращаемыми данными. Если таблицы созданы до вызова Fill, объект SQLDataAdapter просто заполняет существующие таблицы.
' Указать первичный ключ для таблиц
hierDS.Tables("Orders").PrimaryKey = New DataColumn() _
{ hierDS.Tables("Orders").Columns("OrderId")}
hierDS.Tables("OrderDetails").PrimaryKey = New DataColumn() _
{ hierDS.Tables("OrderDetails").Columns("OrderDetailId")}
' Установить между двумя таблицами отношение через внешний ключ
hierDS.Relations.Add("Order_Detail", _
hierDS.Tables("Orders").Columns("OrderId"), _
hierDS.Tables("OrderDetails").Columns("OrderId"))
' Выбрать один заказ из таблицы
orderRow = hierDS.Tables("Orders").Rows(0)
' Выбрать соответствующие ему дочерние строки
detailRows = orderRow.GetChildRows("Order_Detail")
' Работа с коллекцией дочерних строк
For i = 0 To detailRows.Length - 1
detailRow = detailRows(i)
' Что-то делаем со строкой таблицы OrderDetails
strDetail = detailRow("OrderId").ToString & ", " & _
detailRow("OrderDetailId").ToString & ", " & _
detailRow("ItemId").ToString & ", " & _
detailRow("UnitPrice").ToString & ", " &
detailRow("Quantity").ToString)
Next
Catch E As Exception
' Обработать исключение
Finally
' Закрыть соединение и выполнить другую очистку
End Try