views:

90

answers:

2

Can someone help me with the best way to map the following situation in fluent nHibernate? The Address class is used in both Client and Company. How can I store it most efficient in SQL? And what should the mapping look like? I've thought about multiple options, but I'm not experienced enough with nHibernate for these situations:

  1. use 1 address entity and 1 table and use a denominator column to distinguish between address for client and address for company -> how to implement this in nHibernate?

  2. use 1 address entity and 2 tables (ClientAddresses and CompanyAddresses) --> but I can only define 1 table in the mapping of the class Address

  3. use 2 address entities and 2 tables --> not so elegant

I've just stumbled upon this problem when I started implementing the company class and realized it also needed multiple addresses. Up till now I had a Address and Client class and had a one-to-many mapping between them. In the database the Address had an extra column called ClientId. But with introducing the Company class I'm stuck...

Any help would greatly be appreciated.

I'm currently working in the sharparch 1.5 framework, which uses automapping and my mapping files are like this:

public class AddressMap : IAutoMappingOverride<Address>
{
    public void Override(AutoMapping<Address> mapping)
    {
        mapping.Table("addresses");
        mapping.Id(x => x.Id, "AddressGuid")
             .UnsavedValue(Guid.Empty)
             .GeneratedBy.GuidComb();

        mapping.References(x => x.Client, "ClientGuid");

    }
}

Below some more code the illustrate the problem:

Address

public class Address
{
   public virtual string StreetLine1 { get; set; }
   public virtual string StreetLine2 { get; set; }
   public virtual string PostalCode { get; set; }
   public virtual string City { get; set; }
   public virtual string Country { get; set; }
}

which has the following table:

tablename = addresses
fields= AddressGuid, StreetLine1, StreetLine2, PostalCode, City, Country

Client

public class Client
{
    public IList<Address> Addresses {get;set;}
}

Company

public class Company
{
    public IList<Address> Addresses {get;set;}
}
A: 

You could model the relationships as a many-to-many: many companies to many addresses, and many clients to many addresses.

In both your Company and Client mappings:

mapping.HasManyToMany(x => x.Addresses);

This will create two additional tables: one mapping between companies and addresses, another mapping between clients and addresses.

In theory this could allow sharing situations (some companies and clients all sharing have the same address row) which you probably don't want, but as long as your application logic doesn't allow that to happen, you'll be fine and you won't have to do anything tricky with nhibernate.

Gabe Moothart
Tried it but it does not persist the address_id to the shared table
mhenrixon
@mhenrixon Then you're doing something wrong. Maybe you need to set `Cascade.All()` on the association?
Gabe Moothart
I have Cascade.SaveUpdate set and I tried with both inverse not inverse both mapping xml and fluent.
mhenrixon
A: 

It looks like you can implement #1 with nHibernate's <any> mapping. Note that in this case you cannot specify foreign-key constraints.

an example of <any>

Fluent nHibernate syntax

Gabe Moothart
Never tried any. I do see the beauty of it and maybe this is the use case. It also says to be very careful with it and I have no idea what I am doing most of the time so maybe that isn't for me? :)
mhenrixon
I think the "be careful" note is because you don't get referential integrity (enforced in the db) with this method. As long as you're aware of that, you should be fine.
Gabe Moothart

related questions