Вот сценарий:
У меня есть 3 объекта с именами Person, VideoGame и Store.
Один человек может иметь несколько видеоигр
Одна видеоигра может принадлежать многим людям
То же отношение M: N между Store и VideoGames
В БД кроме этих сущностей единственными вещами являются две простые таблицы соединений PersonsVideoGames и StoresVideoGames.
Предположим, что все имеетсвойство Id, и они уникальны.
Бизнес-правила:
- I * не хотят, чтобы видеоигра была в таблице VideoGames , если онане ассоциируется ни с чем (сирота)
- Я делаю хочу это в таблице, если оно связано с хотя бы одним другим объектом
- Вы не управляете VideoGames напрямую, а другие стороны (Store, Person) управляют сохранением / удалением видеоигр.
Возможно ли это сделать с помощью сопоставления NHibernate?Судя по моей реальной реализации проекта, он не работает на базовом уровне Person <-> VideoGame.
В настоящее время NHibernate удалит VideoGame, даже если он по-прежнему связан с другими людьми (это не совсемorphan).
Мое отображение выглядит следующим образом:
Person Имеет 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
Затем, когда я сохраняю человека, я получаю список видеоигр (уже существующих или совершенно новых), а затем использую этот метод набора:
' 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 отношений (например, магазины)?