Операции над данными с иерархической структурой. Разработка распределенных приложений в .NET
Страница 5. Добавление строк


Добавление строк

В дочернюю таблицу строки можно добавлять, только если они соответствуют допустимым (уже существующим) строкам родительской таблицы. Строки, не соответствующие допустимым строкам родительской таблицы, добавлять нельзя.

Новую строку нужно вставить сначала в родительскую таблицу; только после этого в дочернюю таблицу можно добавлять соответствующие строки. По той же причине в процессе синхронизации изменений с базой данных метод Update объекта DataAdapter, соответствующего родительской таблице, следует вызывать первым.

Автоматическое формирование команды Insert

Проблема с автоматически генерируемыми командами вставки в том, что объекту DataSet не возвращается первичный ключ Id для столбца Identity. Для решения этой проблемы мы используем хранимую процедуру, которая возвращает первичный ключ для родительской строки. Тогда появляется возможность применять автоматически формируемые команды вставки для дочерних строк. В следующем примере мы создаем два объекта DataAdapter, заполняющие две таблицы в одном объекте DataSet. Мы задаем отношение между этими двумя таблицами и вставляем в них новые строки. Метод Update объекта DataAdapter, соответствующего родительской таблице (в нашем случае — Order), вызывается первым. Затем вызывается метод Update объекта DataAdapter, соответствующего дочерней таблице (в нашем случае — OrderDetails).

Dim sqlConn As SQLConnection
Dim sqlDAOrder As SqlDataAdapter
Dim sqlDADetail As SqlDataAdapter
Dim hierDS As DataSet
Dim sqlCmdBldrDetail As SqlCommandBuilder
Dim orderRow As DataRow
Dim detailRow As DataRow
Try
' Создать новый объект SQLConnection
sqlConn = New SqlConnection(Common.getConnectionString)
' Создать новый объект SQLDataAdapter для таблицы Order
sqlDAOrder = New SqlDataAdapter()
' Создать новый объект SqlDataAdapter для таблицы OrderDetails
sqlDADetail = New SqlDataAdapter()
' Создать новый DataSet
hierDS = New DataSet()
' Создать новый объект SQLCommandBuilder для автоматической генерации
' выражений Update
sqlCmdBldrDetail = New SqlCommandBuilder(sqlDADetail)
With sqlDAOrder
' Добавить объект SelectCommand
.SelectCommand = New SqlCommand()
' Указать команду Select
With .SelectCommand
.CommandType = CommandType.Text
.CommandText = "Exec GetOrderHeader @OrderId=-1"
.Connection = sqlConn
End With
' Добавить объект InsertCommand
.InsertCommand = New SqlCommand()
' Указать команду Insert
With .InsertCommand
.CommandType = CommandType.StoredProcedure
.CommandText = "InsertOrderHeader"
.Connection = sqlConn
' Определить параметры параметризованного запроса Insert
.Parameters.Add _
(New SqlParameter("@CustomerId", SqlDbType.Int))
' Задать свойство Direction
.Parameters("@CustomerId").Direction = ParameterDirection.Input
' Задать свойство SourceColumn
.Parameters("@CustomerId").SourceColumn = "CustomerId"
.Parameters.Add _
(New SqlParameter("@OrderDate", SqlDbType.DateTime))
' Задать свойство Direction
.Parameters("@OrderDate").Direction = ParameterDirection.Input
' Задать свойство SourceColumn
.Parameters("@OrderDate").SourceColumn = "OrderDate"


.Parameters.Add _
(New SqlParameter("@OrderId", SqlDbType.Int))
' Задать свойство Direction
.Parameters("@OrderId").Direction = ParameterDirection.Output
' Задать свойство SourceColumn
.Parameters("@OrderId").SourceColumn = "OrderId"
End With
' Заполнить таблицу Orders данными
.Fill(hierDS, "Orders")
End With
With sqlDADetail
' Добавить объект SelectCommand
.SelectCommand = New SqlCommand()
' Указать команду Select
With .SelectCommand
.CommandType = CommandType.Text
.CommandText = "Exec GetOrderDetails @OrderId=-1"
.Connection = sqlConn
End With
' Заполнить таблицу Details данными
.Fill(hierDS, "Details")
End With
' Установить связь между таблицами
hierDS.Relations.Add("Order_Detail", _
hierDS.Tables("Orders").Columns("OrderId"), _
hierDS.Tables("Details").Columns("OrderId"))
' Создать новую строку для таблицы Orders
orderRow = hierDS.Tables("Orders").NewRow()
' Указать значения каждого столбца в таблице Orders
orderRow.Item("CustomerId") = 1
orderRow.Item("OrderStatus") = 400
orderRow.Item("OrderDate") = Now()

' Добавить строку к DataSet
hierDS.Tables("Orders").Rows.Add(orderRow)
' Синхронизировать изменения с источником данных
sqlDAOrder.Update(hierDS, "Orders")
' Создать новую строку для таблицы Details
detailRow = hierDS.Tables("Details").NewRow()
detailRow.Item("OrderId") = orderRow.Item("OrderId")
detailRow.Item("ItemId") = 13

' Добавить строку к DataSet
hierDS.Tables("Details").Rows.Add(detailRow)
' Синхронизировать изменения с источником данных
sqlDADetail.Update(hierDS, "Details")
Catch e As Exception
' Обработать исключение
Finally
' Выполнить очистку
End Try

Обратите внимание: если новые строки, добавленные к дочерней таблице, соответствуют новой строке, добавленной к родительской таблице, то для сохранения целостности данных сначала обновляется родительская таблица. Дочерняя строка всегда должна ссылаться на допустимую строку в родительской таблице.

Использование свойства InsertCommand

В этом примере заголовок заказа и его позиции передаются хранимой процедуре в виде XML, что позволяет выполнить транзакцию за одно обращение к базе данных.

Чтобы указать собственное выражение INSERT, выполняемое при вызове метода Update применительно к DataAdapter, следует задать свойство InsertCommand. Значением этого свойства может быть параметризированный запрос или хранимая процедура. Параметры InsertCommand определяются так же, как и параметры объекта Command. Управляемый провайдер SQL поддерживает именованные параметры.

Для каждого параметра нужно установить свойство SourceColumn. Оно сообщает объекту DataAdapter, в каком столбце таблицы содержится значение параметра.


Dim sqlConn As SqlConnection
Dim sqlDAOrder As SqlDataAdapter
Dim sqlDADetail As SqlDataAdapter
Dim hierDS As DataSet
Try
' Создать новое соединение
sqlConn = New SqlConnection(Common.getConnectionString)
' Создать новый объект SqlDataAdapter для таблицы Order
sqlDAOrder = New SqlDataAdapter()
' Создать новый объект SqlDataAdapter для таблицы OrderDetails
sqlDADetail = New SqlDataAdapter()
' Создать новый DataSet
hierDS = New DataSet()
With sqlDAOrder
' Добавить объект SelectCommand
.SelectCommand = New SqlCommand()
' Указать команду Select
With .SelectCommand
.CommandType = CommandType.Text
.CommandText = "Exec GetOrderHeader @OrderId=-1"
.Connection = sqlConn
End With
' Добавить объект InsertCommand
.InsertCommand = New SqlCommand()
' Указать команду Insert
With .InsertCommand
.CommandType = CommandType.StoredProcedure
.CommandText = "InsertOrder"
.Connection = sqlConn
' Задать параметры параметризованного выражения Insert
.Parameters.Add _
(New SqlParameter("@Order", SqlDbType.NVarChar, 4000))
' Установить свойство Direction
.Parameters("@Order").Direction = ParameterDirection.Input
.Parameters.Add _
(New SqlParameter("@OrderId", SqlDbType.Int))
' Установить свойство Direction
.Parameters("@OrderId").Direction = ParameterDirection.Output
' Установить свойство SourceColumn
.Parameters("@OrderId").SourceColumn = "OrderId"
End With
' Заполнить DataSet возвращенными данными
.Fill(hierDS, "Orders")
End With
With sqlDADetail
' Добавить объект SelectCommand
.SelectCommand = New SqlCommand()
' Указать команду Select для объекта sqlDADetail
With .SelectCommand
.CommandType = CommandType.Text
.CommandText = "Exec GetOrderDetails @OrderId=-1"
.Connection = sqlConn
End With
' Заполнить DataSet возвращенными данными
.Fill(hierDS, "Details")
End With
' Установить между двумя таблицами отношение через внешний ключ
hierDS.Relations.Add("Order_Detail", _
hierDS.Tables("Orders").Columns("OrderId"), _
hierDS.Tables("Details").Columns("OrderId"))
' Создать новую строку в таблице Orders
orderRow = hierDS.Tables("Orders").NewRow()
' Задать значение каждого столбца в таблице Orders
orderRow.Item("OrderId") = -1
orderRow.Item("CustomerId") = 1
orderRow.Item("OrderStatus") = 400

' Добавить строку к DataSet
hierDataSet.Tables("Orders").Rows.Add(orderRow)
' Создать новую строку в таблице Details
detailRow = hierDataSet.Tables("Details").NewRow()
detailRow.Item("OrderId") = orderRow.Item("OrderId")
detailRow.Item("ItemId") = 13

' Добавить строку к DataSet
hierDataSet.Tables("Details").Rows.Add(detailRow)
' Создать новую строку в таблице Details
detailRow = hierDataSet.Tables("Details").NewRow()
detailRow.Item("OrderId") = orderRow.Item("OrderId")
detailRow.Item("ItemId") = 12

' Добавить строку к DataSet
hierDataSet.Tables("Details").Rows.Add(detailRow)
sqlDAOrder.InsertCommand.Parameters("@Order").Value = _
hierDataSet.GetXml()
' Синхронизировать изменения с источником данных
sqlDAOrder.Update(hierDataSet, "Orders")
Catch E As Exception
' Обработать исключения
Finally
' Выполнить очистку
End Try
 
« Предыдущая статья   Следующая статья »