2
votes

I'm trying to map the following tables/entities in FNH and seem to be getting nowhere fast!

**Tables**
Contacts
    ID (PK - int - generated)
    ...

PhoneTypes
    ID (PK - varchar - assigned) (e.g. MOBILE, FAX)

ContactPhones
    ContactRefId    (PK - FK to Contacts)
    PhoneTypeRefId  (PK - FK to PhoneTypes)
    ...

(I should note that I am also using the S#arp Architecture framework)

**Entities**
public class Contact : Entity
{
    (The ID property is defined in the Entity base class and is type int)

    public virtual ICollection<ContactPhone> PhoneNumbers { get; set; }
}

public class PhoneType : EntityWithTypedId<string>, IHasAssignedId<string>
{
    (The ID property is defined in the base class and is type string)

    ....
}

public class ContactPhone : EntityWithTypedId<ContactPhoneId>, IHasAssignedId<ContactPhoneId>
{
    public virtual Contact Contact { get; set; }

    public virtual PhoneType PhoneType { get; set; }
    ....
}

I read that it is advisable when working with composite ids, to separate the composite id into a different class. hibernate composite key

public class ContactPhoneId : EntityWithTypedId<ContactPhoneId>, IHasAssignedId<ContactPhoneId>
{
    public virtual Contact Contact { get; set; }

    public virtual PhoneType PhoneType { get; set; }
}
...I could just make this class serializable and override 
Equals and GetHashCode myself instead of using the S#arp Arch base class.

I've tried so many combinations of mappings that I'm now completely confused.

This is my latest shot:

public class ContactMap : IAutoMappingOverride<Contact>
{
    public void Override(AutoMapping<Contact> mapping)
    {
        mapping.HasMany<ContactPhone>(x => x.PhoneNumbers)
            .KeyColumns.Add("ContactRefId")
            .KeyColumns.Add("PhoneTypeRefId")
            .AsSet()
            .Inverse()
            .Cascade.All();
    }
}


public class PhoneTypeMap : IAutoMappingOverride<PhoneType>
{
    public void Override(AutoMapping<PhoneType> mapping)
    {
        mapping.Id(x => x.Id).Column("Id").GeneratedBy.Assigned();
    }
}


public class ContactPhoneMap : IAutoMappingOverride<ContactPhone>
{
    public void Override(AutoMapping<ContactPhone> mapping)
    {
        mapping.Table("ContactPhones");
        mapping.CompositeId<ContactPhoneId>(x => x.Id)
            .KeyReference(y => y.Contact, "ContactRefId")
            .KeyReference(y => y.PhoneType, "PhoneTypeRefId");
    }
}  

I've had many exceptions thrown when trying to generate the mappings, the latest of which is:

Foreign key (FK672D91AE7F050F12:ContactPhones [ContactRefId, PhoneTypeRefId])) 
must have same number of columns as the referenced primary key (Contacts [Id])

Does anyone see anything obvious that I'm doing wrong? I'm new to NH and FNH, which may be obvious from this post. :-) Also, has anyone used Composite Ids like this while using S#arp Architecture? What are the best practices (other than to use surrogate keys :-) ) ?

Many thanks...and sorry about the long post.

1

1 Answers

0
votes

I have a many to many relationship too. I've got mine setup like this:

mapping.HasManyToMany(x => x.Artists).Cascade.All().Inverse().Table("ArtistImages");

The ArtistImages table has primary keys for tables Artists and Images.