0

シナリオは次のとおりです。

Person、VideoGame、Store という 3 つのオブジェクトがあります。

1 人で複数のビデオゲームを所有できる

1 つのビデオゲームは多くの人に属することができます

Store と VideoGames の間の同じ M:N 関係

DB では、これらのエンティティ以外に、2 つの単純な結合テーブル PersonsVideoGames と StoresVideoGames だけがあります。

すべてに Id プロパティがあり、一意であると仮定します。

ビジネスルール:

  • ビデオ ゲームが何にも関連付けられていない場合(孤児) 、ビデオ ゲームを VideoGames テーブルに入れたくありません。
  • 少なくとも1つの他のオブジェクトに関連付けられている場合は、テーブルに入れたい
  • ビデオゲームを直接管理するのではなく、反対側 (Store、Person) がビデオ ゲームの保存/削除を管理します。

NHibernate マッピングを使用してこれを行うことは可能ですか? 私の実際のプロジェクトの実装から、基本的な人物 <-> ビデオゲーム レベルでは機能しないようです。

NHibernate は現在、VideoGame が他の Person に関連付けられている場合でも、その VideoGame を削除します (これは本当に孤児ではありません)。

私のマッピングは次のようになります。

Person は VideoGame の M:N をセットとして持ち、カスケード スタイルの 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

次に、Person を保存するたびに、ビデオ ゲームのリスト (既存のものまたは新しいもの) を取得し、その 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" のようなわかりやすい ID を使用して参照できます。保存は、「DA:O,BatmanAA,LBP2」などの IEnumerable(Of String) を取り込み、それに一致するその Personの DB 内の既存のビデオ ゲームを検索するか、その短いタイトルで新しいドメイン オブジェクトを作成します ( Id と ShortTitle のみがプロパティであると仮定します)。

それで、誰かが何が悪いのか知っていますか?NHibernate は、VideoGame をそのセットから削除するときに、VideoGame が既に他の Person に関連付けられていることを検出しないのはなぜですか?

さらに、これが機能すると仮定すると、このシナリオは、さらに M:N の関係 (ストアなど) を設定した後でも機能しますか?

4

1 に答える 1

1

all-delete-orphanそれほど強力ではありません。他の関係がある場合は、削除カスケードを手動で管理する必要があります。

于 2010-09-01T20:30:14.467 に答える