views:

97

answers:

2

Hi, 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. http://stackoverflow.com/questions/2301259/hibernate-composite-key/2301332#2301332

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.

A: 

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.

CurlyFro
A: 

Perhaps FluentNHibernate isn't able to map this relationship. You might try doing it using hbm files. The examples in this article isn't exactly the same as your situation, but it might be enough to get you started.

http://stackoverflow.com/questions/2183417/fluent-nhibernate-how-to-map-mn-many-to-many-with-composite-keys-on-both-sides

Dan

related questions