views:

145

answers:

2

I have an Address class that I want to use for other objects address info. Below I paste 2 example classes Company and Person that use Address class

public class Company
{
    public virtual string Name { get; set; }
    public virtual string Phone { get; set; }
    public virtual string Fax { get; set; }

    public virtual Address Address { get; set; }
}

public class Person
{
    public virtual string Name { get; set; }
    public virtual string Phone { get; set; }
    public virtual string Fax { get; set; }

    public virtual Address Address { get; set; }
}

public class Address
{
    public virtual string Address1 { get; set; }
    public virtual string CityName { get; set; }
    public virtual string StateName { get; set; }
    public virtual string CountryName { get; set; }

    public virtual AddressOf AddressOf { get; set; }
    public virtual object Owner { get; set; }
}

public enum AddressOf : byte
{
        Company,
    Person
}

My plan is to have an addresses table that I will keep addresses of companies customers etc. Each address will have its unique id and will associate to the owner of the address via another owner_id and owner_type columns.

The way I normally did was I would have address columns on all tables that needed address information(then I could do component mapping for nhibernate) but now I'm thinking that may not be necessary and I can collect all addresses on one common table..

Now my challenge is how I map these to nhibernate. I thought of one-to-one mapping but could not figure how I will map owner_id column which should be foreignly generated from the owner / company, person etc.

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" >
    <class name="Company" table="Companiess">
        <id name="ID" column="ID" type="Int32" unsaved-value="0">
            <generator class="native" />
        </id>

        <property name="Name" />
        <property name="Phone" />
        <property name="Fax" />

        <one-to-one name="Address" class="Address"  />

    </class>
</hibernate-mapping>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
    <class name="Addresses" table="Addresses   ">
        <id name="ID" column="ID" type="Int32" unsaved-value="0">
            <generator class="native" />
        </id>


        <property name="Address1" />
        <property name="CityName" />
        <property name="StateName" />
        <property name="CountryName" />

        <one-to-one "here is where im having trouble, I need to map owners id to owner_id column of Addresses table" ></one-to-one>


    </class>
</hibernate-mapping>

If you are seeing an architectural problem please also let me know as I have not used a separate address table this way before and I'm not yet entirely comfortable about it. Thanks!

+1  A: 

You need the Company and Person classes to implement a common interface. Add a field in Address that will track if the row belongs to a Company or a Person. Then use the <any> tag in the Address mapping. See Ayende's post 'NHibernate Mapping - <any/>' on the subject.

Mufasa
This approach makes me consider keeping the address fields on the same table instead of separate table as it looks like this will complicate things too much.. (i will mark it as answer if there are no better solutions to this problem)
kaivalya
A: 

I'm not sure why you want the bi-directional link from Address to the owner; would that really be necessary? Does an address really have to know who it is owned by?

You might want to consider dropping that relation and come up with a generic 'shared' relation class, like this:

public class Relation
{
  public virtual string Name { get; set; }
  public virtual string Phone { get; set; 
  public virtual string Fax { get; set; }
  public virtual Address Address { get; set; }
}

and...

public class Person : Relation
{
}
public class Company : Relation
{
}

And the mapping file:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" >
    <class name="Relation" table="Relations">
        <id name="ID" column="ID" type="Int32" unsaved-value="0">
            <generator class="native" />
        </id>

        <property name="Name" />
        <property name="Phone" />
        <property name="Fax" />
        <Component name="Address" class="Address" >
        ... address fields...
        </Component>

        <joined subclass="Person..." />

        <joined subclass="Company..." />


    </class>
</hibernate-mapping>
Hace