更新
好吧,正如斯图尔特查尔斯和詹姆斯格雷戈里告诉我的那样,我的模型开始时很奇怪。显然,在区分不同类型的关系时,类之间的双向引用并没有完成,显然是有充分理由的。
我撕下模型,使用用户和Fiches之间的HasManyToMany将其更改为另一个模型,然后我添加了一些编码验证,以确保我的用户无法链接到多个Fiche。
所以我想这个问题的答案是一种警告:“不要这样做”;)
感谢您抽出时间回答!
大家好
正确使用Fluent Nhibernate的道路是艰难的,因为我开始感到非常难过,我认为寻求帮助不会有什么坏处。事情就是这样。
罪魁祸首
我有以下两个类,Fiche和User。 Fiche必须拥有用户所有者,并且可以拥有许多用户关注者。另一方面,用户可以选择性地链接回一个且仅一个Fiche。 (EntityUpdateTrace基类包含guid id和创建/修改时间,用于PreSave / PreUpdate)
Public Class Fiche
Inherits EntityUpdateTrace(Of Fiche)
Private m_Owner As User
Public Property Owner() As User
' snip
Private m_Followers As IList(Of User)
Public Property Followers() As IList(Of User)
' snip
End Class
Public Class User
Inherits EntityUpdateTrace(Of User)
Private m_Fiche As Fiche
Public Property Fiche() As Fiche
' snip
End Class
然后我有以下映射
Public Class FicheMapping
Inherits ClassMap(Of Fiche)
Public Sub New()
[Not].LazyLoad()
Id(Function(f As Fiche) f.Id).GeneratedBy.GuidComb()
References(Of User)(Function(f As Fiche) f.Owner).Not.Nullable()
HasMany(Of User)(Function(f As Fiche) f.Followers).Inverse()
End Sub
End Class
Public Class UserMapping
Inherits ClassMap(Of User)
Public Sub New()
[Not].LazyLoad()
Id(Function(a As User) a.Id).GeneratedBy.GuidComb()
References(Of Fiche)(Function(a As User) a.Fiche).Nullable()
End Sub
End Class
问题
我到底做错了什么? :) 我似乎无法使用这个模型,虽然看起来很简单。
Fiche加载与其相关的所有用户;听起来合乎逻辑,我想我应该区分一个特定的参数,但因为它完全是数据库相关的东西,我真的不喜欢这个想法(我试图保持这些类干净,作为域名卫生的练习)。因此,如果Fiche veryImportantFiche是由Alice创建并且后跟Bob,则在重新加载关注者时我会找到Alice和Bob。有没有办法区分这两种类型的用户?
我想在数据库中使用List来保持关注者的顺序,但是只要我将映射更改为
HasMany(Of User)(函数(f作为Fiche)f.Followers).AsList()。Inverse()
弹出以下错误:
集合的null索引列: 追随者
关于这个错误的信息量并不是真的让人不知所措,这让我想到我对这个模型采取了错误的方式,这让我回到了第一个问题......我到底做错了什么?
感谢所有人的阅读,以及对此的任何见解!
答案 0 :(得分:1)
由于列表的语义而发生List
错误。这很棘手,因为默认情况下包也会映射到IList
,但这是由于.NET框架中缺少带有“bag”语义的集合类型。在概念上,在“包”中,没有订单,因为物品只是被丢入包中并以任何顺序被移除并且可以容易地在包内移动。但是,列表本身是有序的并且已编入索引(将其视为具有附加语义的数组,因此每个元素都具有唯一的索引值)。您收到的错误消息表明NHibernate需要一个存储每个元素的索引值的列(因此它必须是唯一的,因为它是IList
,蚂蚁整数值)。由于您似乎没有索引列,因此您必须以其他方式对它们进行排序,可能是在查询中添加ORDER BY子句。
至于第一个问题,您可能需要重新考虑如何使用它。实际上,您可以利用NHibernate filters,但我没有任何经验可以说明它是如何运作的。您的Followers
集合实际上是与Fiche
(引用User
的所有Fiche
)相关的所有用户,因此更像是RelatedUsers
。使用存储库模式,您可以使用像FindFollowers(Fiche fiche)
这样的方法来查询RelatedUsers
不等于User
的所有Owner
。这种模式可能会对您有所帮助,因为您希望订购User
。像(C#,Criteria查询):
session.CreateCriteria(typeof(Fiche))
.CreateCriteria("RelatedUsers", JoinType.InnerJoin)
.Add(Restrictions.Not(Restrictions.Eq("Id", fiche.Owner.Id)))
.AddOrder(Order.Asc("PropertyNameToOrderBy"))
.List<User>();
答案 1 :(得分:1)
听起来你需要多对多而不是一对多。这样,单个用户可以被多个小提取引用。
至于集合的排序,除非您的表中有索引列,否则AsList
将无效;这是一个包含每个记录的数值的列,没有间隙。如果您不想要此行为,则需要使用order-by
属性。