Update
Well, as i was told by Stuart Charles and James Gregory, my model was weird enough to begin with. Apparently double-way references between classes while discriminating between the different kinds of relations isn’t done, and apparently for a very good reason.
I tore the model down, changed it to a different one using HasManyToMany between Users and Fiches and then i added some coded validations to make sure my Users couldn’t be linked to more than one Fiche.
So i guess the answer to this kind of problem is kind of a warning: “Don’t do it” 😉
Thank you both for taking time to answer!
Hello everyone
The path to a correct use of Fluent Nhibernate is a hard one, and since i’m beginning to feel really stumped, i figured it wouldn’t hurt to ask for help. Here’s the thing.
The culprits
I have the following two classes, Fiche and User. A Fiche must have a User owner , and can have many User followers. On the other hand, a User can optionally be linked back to one and only one Fiche. (The EntityUpdateTrace base class contains a guid id and Create/Modification times, for PreSave/PreUpdate use)
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
I then have the following mapping
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
The question
What the hell am i doing wrong? 🙂
I can’t seem to have this model working although it looks deceptively simple.
-
Fiche loads all User its related to; sounds logical, and i guess i should discriminate on a specific parameter, but since it would be something entirely database related i don’t really like the idea (i’m trying to keep the classes squeaky clean as an exercice in domain hygiene). So if the Fiche veryImportantFiche is created by Alice and followed by Bob, when reloading the followers i find Alice and Bob. Is there a way to discriminate between the two type of User?
-
I would like to use a List in the database to keep the followers ordered, but as soon as i change the mapping to
HasMany(Of User)(Function(f As Fiche) f.Followers).AsList().Inverse()
the following error pops up:
null index column for collection:
Followers
The amount of information on this error is not really overwhelming, which leads me to suppose i’m taking the wrong way to this model, which leads me back to the fist question… What the hell am i doing wrong?
Thank you all for reading, and for any insight into this!
The
Listerror happening due to the semantics of lists. It’s tricky because bags also get mapped toIListby default, but this is due to the lack of a collection type with “bag” semantics in the .NET framework. In a “bag,” conceptually, there is no order because items are just thrown into the bag and removed in any order and could easily be moved around inside the bag. A list, however, is inherently ordered and indexed (think of it as an array with additional semantics, so each element has an unique index value). The error message you are getting indicates that NHibernate wants a column that stores the index value for each element (so it must be unique and, since it’s anIList, ant integer value). Since you don’t appear to have an index column, you’ll have to order them another way, perhaps by adding an ORDER BY clause in your query.As for the first issue, you might need to rethink how you are working with this. Actually, you might be able to leverage NHibernate filters, but I don’t have any experience with them to say how it might work out. Your
Followerscollection is really all users that are related to theFiche(allUsers that referenceFiche), so it’s more likeRelatedUsers. Using the Repository Pattern, you could have a method likeFindFollowers(Fiche fiche)that would query for allRelatedUserswhere theUserdoes not equal theOwner. This pattern might additionally benefit you since you wanted to have theUsers be ordered. Something like (C#, Criteria query):