在M:N关系上设置“全部删除孤立项”时,NHibernate未检测到其他关联的问题

在M:N关系上设置“全部删除孤立项”时,NHibernate未检测到其他关联的问题,nhibernate,many-to-many,orphan,Nhibernate,Many To Many,Orphan,以下是场景: 我有三个对象,分别是人、视频游戏和商店 一个人可以玩很多电子游戏 一个电子游戏可以属于许多人 商店和电子游戏之间存在着同样的M:N关系 在DB中,除了这些实体之外,只有两个简单的连接表PersonVideoGames和StoresVideoGames 假设所有内容都有一个Id属性,并且它们是唯一的 业务规则: 如果某个视频游戏与任何事物(孤儿)无关,我不希望它出现在视频游戏表中 如果它与至少一个其他对象关联,则我不希望它出现在表中 您不直接管理视频游戏,而是由其他方(商店、个人)

以下是场景:

我有三个对象,分别是人、视频游戏和商店

一个人可以玩很多电子游戏

一个电子游戏可以属于许多人

商店和电子游戏之间存在着同样的M:N关系

在DB中,除了这些实体之外,只有两个简单的连接表PersonVideoGames和StoresVideoGames

假设所有内容都有一个Id属性,并且它们是唯一的

业务规则:

  • 如果某个视频游戏与任何事物(孤儿)无关,我不希望它出现在视频游戏表中
  • 如果它与至少一个其他对象关联,则我不希望它出现在表中
  • 您不直接管理视频游戏,而是由其他方(商店、个人)管理保存/删除视频游戏
使用NHibernate映射可以做到这一点吗?从我的实际项目实施来看,它似乎不适用于基本的个人视频游戏级别

NHibernate目前将删除该视频游戏,即使它仍然与其他人有关联(它不是真正的孤儿)

我的映射看起来像:

已将视频游戏的M:N作为一个集合,并启用了级联样式“全部删除孤立项”

视频游戏 将M:N个人作为一个集合,启用了延迟加载、反向和级联样式的保存更新

此人的视频游戏财产没有公共设置器。它具有如下功能:

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)
视频游戏可以使用更友好的ID(如“ShortTitle”)作为示例。然后保存一个IEnumerable(字符串),如“DA:O,BatmanAA,LBP2”等,然后在数据库中查找与之匹配的任何现有视频游戏,或者创建一个具有该短标题的新域对象(假定只有Id和短标题是唯一的属性)

那么,有人知道怎么回事吗?为什么NHibernate在从视频游戏集中删除视频游戏时,没有检测到视频游戏已经与其他人关联


此外,假设我能做到这一点,那么一旦我建立了更多的M:N关系(比如商店),这种情况还会起作用吗?

all delete orphan
没有那么强大。如果您有其他关系,则必须手动管理删除级联。

我预料到了;您建议如何解决此问题,当PersonVideoGames中的行被删除时,是否有方法检查视频游戏的关联?我可以看到一个DB级别的触发器,那么.NET/NHibernate方法呢?这实际上是模型的责任。删除关联时,应该检查相关实体的其他关联的Count()。这很有意义。我认为除了黑客和砍杀NHibernate来检查孤儿的关联之外,如果您指定了这一点(我认为这是可以做到的?),在代码中处理它可能是最好的选择。