Hi,
I'm working on the architecture for a large project which is mapping to a legacy database. We have a CRM system which uses the basic principle of Person and Organisation inherited from abstract Party. There is a UserAccount 1:0..1 attached to the Party for organisations and people that have access to the system. There is a reference back to the Party from the user. We are using Spring to load stuff from hibernate. Lazy loading is on.
----
Classes:
Code:
class UserAccount {
public virtual long Id { get; set; }
public virtual Party Party { get; set; }
public virtual string UserName { get; set; }
public virtual string Password { get; set; }
}
abstract class Party {
public virtual long Id { get; set; }
public virtual UserAccount UserAccount { get; set; }
}
class Person : Party {
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string Name { get { return this.FirstName + ' ' + this.LastName; }}
}
class Organisation : Party {
public virtual string OrganisationName { get; set; }
public virtual string Name { get { return this.OrganisationName; }}
}
----
Mapping:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="..." namespace="..." default-lazy="true" default-cascade="save-update" schema="CRM.dbo">
<class name="Party" table="VParty">
<id name="Id" type="Int64" unsaved-value="0" column="CRMContactId">
<generator class="native"/>
</id>
... normal properties ...
<joined-subclass name="Person" extends="Party" table="VPerson">
<key column="CRMContactId"/>
... stuff ...
</joined-subclass>
<joined-subclass name="Organisation" extends="Party" table="VCorporate">
<key column="CRMContactId"/>
... stuff ...
</joined-subclass>
</class>
<class name="UserAccount" table="[TUser]">
<!-- Identity mapping -->
<id name="Id" column="UserId" type="Int64">
<generator class="native"/>
</id>
... normal properties ...
<many-to-one name="Party" class="Party" column="CRMContactId" unique="true" fetch="select"/>
</class>
</hibernate-mapping>
----
Repository:
Code:
public User RetrieveByUserName(string userName) {
Assert.IsNotNull(userName, "userName");
IList<User> users = HibernateTemplate.ExecuteFind<User>(delegate(ISession session)) {
return session.CreateQuery("from User u where u.UserName = ?").SetParameter(0, userName).List<User>();
}
if (users.Count == 1)
return users[0];
return null;
}
----
Problem:
Our login routine needs to determine the current user's display name. We expect to do this:
User u = userRepository.RetrieveByUserName("joe.bloggs");
Assert.That(u.Party, Is.TypeOf(typeof(Person)); // FAIL!
u.Party should be type of Person or Organisation, but it is appearing as only Party. As it is a lazy loading proxy, we can't cast it to Person or Organisation or late-bind the properties on it through reflection.
Ultimately, we are expecting to load the user and via our own reflective late binding technology do:
string userName = (string)ReflectOMatic(u, "Party.Name");
We need Party to be Organisation or Person rather than a proxy for the abstract for this to work.
Any ideas?[/code]