типизированный набор данных, каскадное удаление записей дочерней таблицы

У меня есть типизированный набор данных с двумя такими таблицами:

Таблица A (родительская таблица)

ID  MessageID   
1     1
2     1
3     2
4      3

Таблица B (дочерняя таблица)

ID  MessageID   
1     1
2     2
3     3

У меня есть связь между таблицей A и таблицей B в столбце MessageID. Правило удаления установлено на Каскад. Я не могу изменить дизайн этих таблиц, он такой, какой он есть.

Таблица A содержит две записи с MessageID 1. Если я удалю только одну из них, дочерняя запись будет удалена из таблицы B, что приведет к созданию потерянной записи во второй родительской таблице. Есть ли способ удалить только в том случае, если нет других родительских записей, разделяющих MessageID?


person Bremer    schedule 04.05.2011    source источник


Ответы (1)


Вы можете создать триггер вместо каскадного -удалить, например (MS SQL-Server, не проверено):

CREATE TRIGGER [dbo].[trDeleteTableB] ON [dbo].[TableA]
    FOR DELETE
    AS
    DELETE FROM TableB
    WHERE (MessageID IN
         (SELECT MessageID
           FROM  DELETED
           WHERE (NOT EXISTS
                 (SELECT * FROM  TableA
                  WHERE (TableA.MessageID = DELETED.MessageID)))))

Другая идея состоит в том, чтобы расширить типизированный набор данных. Если вы хотите расширить функциональность, вы не можете изменить сгенерированные классы в DatesetName.designer.cs/vb (он будет воссоздан при любом изменении), но файл без конструктора в его имени (создайте его, если он не существует). Затем вам нужно расширить частичный класс DataTable (посмотрите в файле конструктора, если вы не знаете точное имя, обычно это TableBDataTable).

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

Partial Class Datset1
    Partial Class TableBDataTable
        Private Sub TableB_RowDeleting(ByVal sender As Object, ByVal e As TableBRowChangeEvent) Handles Me.TableBRowDeleting
            If e.Action = DataRowAction.Delete Then
                '*** check here if there is another TableARow with this MessageID ***'
                e.Row.RejectChanges()
            End If
        End Sub
    End Class
End Class
person Tim Schmelter    schedule 04.05.2011
comment
Я пытаюсь сделать это только в наборе данных. Я не собираюсь обновлять SQL этими изменениями. (не буду утомлять вас причинами) - person Bremer; 05.05.2011
comment
Правило удаления также находится на стороне базы данных. Тогда у вас есть только вариант снять каскад-удаление и проверить в приложении, нужно ли удалять ребенка или нет. - person Tim Schmelter; 05.05.2011
comment
Вот чего я боялся. Спасибо. - person Bremer; 05.05.2011
comment
@Bremer: у меня была другая идея, и я отредактировал свой ответ, посмотри. - person Tim Schmelter; 05.05.2011
comment
Я сам придумал такое же решение, и оно отлично работает! На самом деле я добавил свой код обработчика событий в класс, который использует набор данных. Ваше размещение в частичном классе еще лучше. Спасибо! - person Bremer; 05.05.2011