这是场景:
我有 3 个对象,分别称为 Person、VideoGame 和 Store。
一个人可以拥有多个视频游戏
一个 VideoGame 可以属于多个 Person
Store 和 VideoGames 之间存在相同的 M:N 关系
在数据库中,除了这些实体之外,唯一的就是两个简单的连接表 PersonsVideoGames 和 StoresVideoGames。
假设所有东西都有一个 Id 属性并且它们是唯一的。
商业规则:
- 如果视频游戏与任何内容(孤儿)无关,我不希望视频游戏出现在 VideoGames 表中
- 如果它与至少一个其他对象相关联,我确实希望它在表中
- 您不直接管理 VideoGames,而是由其他方(商店、人员)管理保存/删除视频游戏。
使用 NHibernate 映射可以做到这一点吗?从我的实际项目实施来看,它似乎不适用于基本的 Person <-> VideoGame 级别。
NHibernate 当前将删除 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
然后,每当我保存一个人时,我都会得到一个视频游戏列表(现有的或全新的),然后使用该 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)
可以使用更友好的 ID(例如“ShortTitle”)来引用视频游戏。保存然后接受一个 IEnumerable(Of String) 像 "DA:O,BatmanAA,LBP2" 等,然后在数据库中找到匹配它的那个人的任何现有视频游戏,或者创建一个具有该短标题的新域对象 (假设只有 Id 和 ShortTitle 是唯一的属性)。
那么,有谁知道出了什么问题?当 NHibernate 从该集合中删除一个 VideoGame 时,它为什么没有检测到一个 VideoGame 已经与其他 Persons 相关联?
此外,假设我得到了这个工作,一旦我建立了更多的 M:N 关系(比如商店),这个场景甚至会工作吗?