Проблема с 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 не такой мощный. Если у вас есть другие отношения, вам придется управлять каскадным удалением вручную.

Другие вопросы по тегам