Проблема с NHibernate, не обнаруживающей другие ассоциации, когда all-delete-orphan установлен в отношении M:N
Вот сценарий:
У меня есть 3 объекта, которые называются Person, VideoGame и Store.
Один человек может иметь много видеоигр
Одна видеоигра может принадлежать многим людям
То же самое отношение M:N между Store и VideoGames
В БД единственными вещами, кроме этих сущностей, являются две простые таблицы соединений PersonsVideoGames и StoresVideoGames.
Предположим, что у всех есть свойство Id, и они уникальны.
Бизнес правила:
- Я не хочу, чтобы видеоигра была в таблице VideoGames, если она ни с чем не связана (сирота)
- Я хочу, чтобы это было в таблице, если оно связано хотя бы с одним другим объектом
- Вы не управляете VideoGames напрямую, а другие стороны (Store, Person) управляют сохранением / удалением видеоигр.
Возможно ли это сделать с помощью картографирования NHibernate? Судя по моей реальной реализации проекта, он не работает на базовом уровне Person <-> VideoGame.
NHibernate в настоящее время удалит VideoGame, даже если оно по-прежнему связано с другими людьми (на самом деле это не сирота).
Мое отображение выглядит так:
Человек имеет M:N VideoGame в комплекте, с включенным каскадным стилем all-delete-orphan.
VideoGame имеет набор M:N Person с включенным сохранением-обновлением с отложенной загрузкой, инверсией и каскадным стилем.
Person не имеет общедоступного сеттера для своего свойства VideoGames. У него есть такая функция:
Public Overridable Sub SetVideoGames(ByVal games As IEnumerable(Of VideoGame))
If Me.VideoGames Is Nothing Then Exit Sub
' Add if the game isn't in the old list.
For Each g In games
If Not Me.VideoGames.Any(Function(g2) g2.Id = g.Id) Then
Me.VideoGames.Add(usr)
End If
Next
' Remove if the game isn't in the new list
For Each g In Me.VideoGames.ToList()
If Not games.Any(Function(g2) g2.Id = g.Id) Then
Me.VideoGames.Remove(g)
End If
Next
End Sub
Затем, когда я сохраняю персонажа, я получаю список видеоигр (уже существующих или совершенно новых), а затем использую этот метод set:
' listOfVideogames is just a list of ShortTitle strings
Dim result As New List(Of VideoGame)()
Dim newGames As New List(Of VideoGame)()
Dim existingGames As IList(Of VideoGame) ' = Session.Get(blah, gets the existing games for this person)
' Add the existing games to the result set
result.AddRange(existingGames)
' Get any titles from the given list not in the existing list
For Each title In listOfVideogames.Except(existingGames.Select(Function(g) g.ShortTitle))
Dim newGame As New VideoGame() With {
.ShortTitle = title
}
newGames.Add(newGame)
Next
' Add them to the resultset
result.AddRange(newGames)
existingPerson.SetVideoGames(result)
' Do other updates
MyNHibernateDataProvider.Save(existingPerson)
К видеоигре можно обратиться, используя в качестве примера более дружественный идентификатор, такой как "ShortTitle". Затем сохранение принимает IEnumerable(Of String), такой как "DA:O,BatmanAA,LBP2" и т. Д., А затем находит любые существующие в БД видеоигры для этого персонажа, которые соответствуют ему, или создает новый объект домена с таким коротким заголовком (предположим, что только Id и ShortTitle являются единственными свойствами).
Итак, кто-нибудь знает, что не так? Почему NHibernate не обнаруживает, что VideoGame уже связана с другими людьми, когда он удаляет VideoGame из этого набора?
Кроме того, предполагая, что это работает, сработает ли этот сценарий после того, как я установлю больше отношений M:N (например, Магазины)?
1 ответ
all-delete-orphan
не такой мощный. Если у вас есть другие отношения, вам придется управлять каскадным удалением вручную.