C# – Fluent NHibernate Inheritance Issue

cfluent-nhibernateinheritance

I have a db setup with 3 tables

t_DataItem
 pk id int auto
 isActive bit 0
 dateCreated datetime getdate()
 parentId int null

t_User
 pk id int 
 firstName varchar(50)
 lastName varchar(50)

t_Email
 pk id int
 address varchar(50)

so now i have 3 classes, each one representing the respective item, however both User and Email inherit from DataItem.

public class DataItem
    {
        public virtual int Id { get; private set; }
        public virtual DateTime DateCreated { get ; set; }
        public virtual bool IsActive { get; set; }
        public virtual DataItem Parent { get; set; }

        public DataItem()
        {
            DateCreated = DateTime.Now;
        }
    }


public class Email : DataItem
    {
        public virtual string Address { get; set; }
    }

public class User : DataItem
    {
        public virtual string FirstName { get; set; }
        public virtual string LastName { get; set; }

        public virtual IList<Email> Emails { get; private set; }

        public  User()
        {
            Emails = new List<Email>();
        }

        public virtual void AddEmail(Email email)
        {
            Emails.Add(email);
        }
    }

So when I save a user or email, it should save a dataitem record first, passing it's id to the id of user or email (any subclass really).

I have that portion working.. my problem lies in the mapping for setting up the

DataItem Mapping to have a Reference to parent, and the HasMany in the UserMap that corresponds to the emails.

I can't get it to save the Email, with it's DataItem ParentId filled out to the User.Id

So if I had a user record, i should have a corresponding dataitem record

if I had an email record, I should have a corresponding dataItem record with it's parentId set to the id of the user record id.

Hopefully I've explained that right…

Can someone please show me an example of how I would map this out using Fluent NHibernate?

My mappings are as follows

public class DataItemMap : ClassMap<DataItem>
    {
        public DataItemMap()
        {
            Table("t_DataItem");
            Id(map => map.Id);
            Map(map => map.DateCreated).Nullable();
            Map(map => map.IsActive);
            References(map => map.Parent).Column("parentid");
        }
    }

public class EmailMapping : SubclassMap<Email> 
    {
        public EmailMapping()
        {
            Table("t_emails");
            KeyColumn("id");
            Map(email => email.Address);
        }
    }

public class UserMapping : SubclassMap<User>
    {
        public UserMapping()
        {
            Table("t_Users");
            KeyColumn("id");
            Map(user => user.FirstName);
            Map(user => user.LastName);
            HasMany(user => user.Emails).KeyColumn("id").Cascade.All();
        }
    }

I love how it auto creates the dataitem record and grabs it's id and stores it into my user or email table.. now if i could get the last piece of the puzzle figured out where when i save an email, not only does it save the dataitem record, but fills out the parentid, and then when i pull the emails for a user, it checks the user id against the parent id on the join..

if this level of inheritance isn't possible, please let me know.

if it is, could you please provide me to the proper tutorial or help by correcting my class maps?

thanks!

Best Answer

figured it out

i had to change my HasMany mapping to include the DataItem type so that it knew to pull the field parentId from the DataItem table instead of my email table (where the field doesn't exist)

HasMany<DataItem>(user => user.Emails).KeyColumn("parentid").Cascade.All();

then in my User class change the method AddEmail to

public virtual void AddEmail(Email email)
{
    email.Parent = this;  //forgot to set it's parent..
    Emails.Add(email);
}

awesome tool.. very powerful!