Страница 5 из 8
Добавление строкВ дочернюю таблицу строки можно добавлять, только если они соответствуют допустимым (уже существующим) строкам родительской таблицы. Строки, не соответствующие допустимым строкам родительской таблицы, добавлять нельзя. Новую строку нужно вставить сначала в родительскую таблицу; только после этого в дочернюю таблицу можно добавлять соответствующие строки. По той же причине в процессе синхронизации изменений с базой данных метод 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
|