I have a following database scheme setup which I can't really change.
User
----
Id (primary key)
[Some simple properties...]
UserAdditionalData
------------------
Id (primary key)
[Some simple properties...]
USERID (foreign key to User)
It's clear that the User
table doesn't really have any recollection whether or not it is linked to a UserAdditionalData
record, so I don't think I can call this a true one-to-one mapping here since they also don't share a mutually exclusive PK.
However, in practice, I would like to be able to work on a User
object and for example check if it has a UserAdditionalData
record and if so, access its properties.
I've set up my BDO as such:
public class User
{
[Some simple properties...]
public virtual UserAdditionalData UserAdditionalData { get; set; }
}
public class UserAdditionalData
{
[Some simple properties...]
public virtual User User { get; set; } /* I have this here,
but I don't really ever
have to access it in this
direction */
}
I've set up my mapping as such:
public UserMapping()
{
Table("USER");
[Some simple properties...]
HasOne(x => x.UserAdditionalData).Cascade.None();
}
public UserExtraMapping()
{
Table("USER_ADDITIONAL_DATA");
[Some simple properties...]
References(x => x.User, "USERID").Unique();
}
This all compiles, but I see that my UserExtra object (when accessed via a User object) is always null. I've tried a lot of different ways to go about it, read a lot on implementing this as a one-to-many. However, I'm still not being able to get it to work.
Any help would be much appreciated.
Thanks!
[Small UPDATE]: I only have to query the database, not save to it if that's relevant in any way.
Based on your small update, I would go with a simplified mapping. We would profit from NHibernate real mapping power, and also optimize the User loading. All that because we do need Read-Only mapping.
Firstly, we should introduce simple int
property UserId
on the Additional class
// extra class is having an int property containig the foreign key
public class UserAdditionalData
{
public virtual int UserId { get; set; }
}
// that would be the mapping:
public UserExtraMapping()
{
...
Map(x => x.UserId, "USERID");
}
Now, we will use well optimized mapping for lazy loading many-to-one
(I.e. in comparison with one-to-one which loads both ends always, here we will get the reference data only if really needed!)
public UserMapping()
{
...
References(x => x.UserAdditionalData)
.LazyLoad()
.PropertyRef(e => e.UserId)
.Not.Insert()
.Not.Update()
;
}
So, for readonly I would do the best to use many-to-one
mapping (References()
)
see also: