Проблема с NHibernate не обнаружение других ассоциаций, когда all-delete-orphan установлен на отношение M: N - PullRequest
0 голосов
/ 01 сентября 2010

Вот сценарий:

У меня есть 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 отношений (например, магазины)?

1 Ответ

1 голос
/ 02 сентября 2010

all-delete-orphan не так сильно.Если у вас есть другие отношения, вам придется управлять каскадным удалением вручную.

...