Отношения Master-Detail не каскадируются при вставке в ADO.NET - PullRequest
0 голосов
/ 11 ноября 2010

Я пытался обработать вставку новой основной записи и связанных дочерних записей в Winforms, используя IronPython (разрабатывается в SharpDevelop 4) для SQL Server, хотя я думаю, что это общая проблема ADO.NET.Форма всегда содержит только одну основную запись (бронирование) и много подробных записей (строк).Если основная запись уже существует, я могу вставлять дочерние записи без проблем, но мои отношения, по-видимому, не каскадируются, если добавляется новая запись бронирования.

Специальный код - сначала я добавляю свои отношения следующим образом:

parentColumn = self._dataSetBookings.Tables["booking"].Columns["intBookingID"]
childColumn = self._dataSetBookings.Tables["lines"].Columns["intBookingID"]
bookingRelationship = DataRelation("mediabooking",parentColumn,childColumn,True)
self._dataSetBookings.Relations.Add(bookingRelationship)
self._dataSetBookings.EnforceConstraints = True

intBookingID - это столбец идентификаторов в таблице бронирования.

Моя процедура обновления применений выглядит следующим образом, обратите внимание на событие, добавленное в обновленную строку.Используемые команды sql - это, по сути, 'select * откуда intBookingID = @intBookingID)

# update booking
adapter = SqlDataAdapter()
adapter.RowUpdated += self.AdapterUpdateBooking
cmd = adapter.SelectCommand = self.conn.CreateCommand()

cmd.CommandText = self.bookingSqlCmd
parameter = cmd.Parameters.Add("@intBookingID", SqlDbType.Int)
parameter.Value = self.BookingID 

builder = System.Data.SqlClient.SqlCommandBuilder(adapter)
adapter.InsertCommand = builder.GetInsertCommand()
adapter.UpdateCommand = builder.GetUpdateCommand()
adapter.Update(self._dataSetBookings,"booking")

# update lines
adapter = SqlDataAdapter()
cmd = adapter.SelectCommand = self.conn.CreateCommand()             
cmd.CommandText = self.lineSqlCmd
parameter = cmd.Parameters.Add("@intLineBookingID", SqlDbType.Int)
parameter.Value = self.BookingID 

builder = System.Data.SqlClient.SqlCommandBuilder(adapter)
adapter.InsertCommand = builder.GetInsertCommand()
adapter.UpdateCommand = builder.GetUpdateCommand()
adapter.UpdateCommand = builder.GetDeleteCommand()      
adapter.Update(self._dataSetBookings,"lines")

И, наконец, событие RowUpdated, которое запускается только один раз для строки бронирования, поэтому мы можем получить идентификатор только что вставленной записи

    def AdapterUpdateBooking(self, sender, e):
    cmd = self.conn.CreateCommand()
    #cmd.CommandText = "SELECT SCOPE_IDENTITY()" - this does not work!
    cmd.CommandText = "SELECT @@IDENTITY "
    newBookingID = cmd.ExecuteScalar()

    if newBookingID != System.DBNull:
        for bookingRow in self._dataSetBookings.Tables["booking"].Rows:
            bookingRow["intBookingID"] = newBookingID

При отслеживании этого, когда применяются обновления, правильное значение идентификатора извлекается с помощью вызова «SELECT @@ IDENTITY» для новой записи (но SCOPE_IDENTITY возвращает ноль, что я не понимаю и может бытьключ?).Однако когда значение применяется к полю intBookingID в таблице Master (резервирование), оно не приводит к каскадному обновлению поля intBookingID в таблице подробностей (строк), и вставка завершается неудачно.

Однако, если основная запись (резервирование)был загружен из базы данных и добавлены новые строки, связь работает, поле intBookingID установлено правильно, и вставка прошла успешно.

Мне кажется, что я упускаю что-то тривиальное, но что я делаю не так?

1 Ответ

0 голосов
/ 25 ноября 2010

Вы кодировали для каскадирования?Я этого не вижуПопробуйте это.

ForeignKeyConstraint oFKey;
oFKey = new ForeignKeyConstraint("BookingForeignkey", parentColumn, childColumn);
oFKey.DeleteRule = Rule.Cascade;
oFKey.UpdateRule = Rule.Cascade;
oFKey.AcceptRejectRule = AcceptRejectRule.Cascade;
self._dataSetBookings.Tables["booking"].Constraints.Add(oFKey);
self._dataSetBookings.EnforceConstraints = True

Вы можете прочитать это: Ограничения DataTable (ADO.NET)

РЕДАКТИРОВАТЬ: Я не понимаю эту часть

if newBookingID != System.DBNull:
        for bookingRow in self._dataSetBookings.Tables["booking"].Rows:
            bookingRow["intBookingID"] = newBookingID

Почему вы присваиваете всем строкам 'newBookingID'?Исходя из этого, я предполагаю, что первичные ключи не могли быть определены для наборов данных.Если бы они были, строка назначения, должно быть, выдавала какую-то ошибку.

...