views:

40

answers:

1

I think I probably know that the most common suggestion will be "change the database schema" but unfortunately it's one of those "I'm stuck with a legacy database" situations.

Basically I want to map the following using Fluent NHibernate

CREATE TABLE Person (PersonId int)
CREATE TABLE Organisation (OrganisationId int)
CREATE TABLE OwnedPhoneNumber (Id int, PersonId int, OrganisationId int, 
PhoneNumber varchar(50))

interface IPhoneNumberOwner
{
    int Id {get; set;}
}
class Person : IPhoneNumberOwner
{
  public virtual int Id {get; set;}
  public virtual ISet<OwnedPhoneNumber> PhoneNumbers {get; set;}
}
class Organisation : IPhoneNumberOwner
{
  public virtual int Id {get; set;}
  public virtual ISet<OwnedPhoneNumber> PhoneNumbers {get; set;}
}
class OwnedPhoneNumber
{
  public virtual int Id {get; set;}
  public virtual IPhoneNumberOwner Owner {get; set;}
  public virtual string PhoneNumber {get; set;}
}

My question is how do I create the ClassMap file for the OwnedPhoneNumber class to determine the column to use when persisting an entity i.e. if it's a Person object use the PersonId column and if it's an Organisation use the OrganisationId column. Mapping the collections from the parent classes is no problem.

Hopefully I've included enough detail to explain the problem but obviously shout if not.

A: 

Noting this in case anyone comes across the same issue but I've found a workaround that some may like (and some may not). After some less than helpful answers I've come to the conclusion that (leaving the database schema discussions aside) this can't be done with nhibernate. I therefore decided to create two views in the database and present these as tables to nhibernate in the mapping. i.e.

CREATE VIEW dbo.vw_PersonPhoneNumber
AS
SELECT  pn.Id,
    pn.PersonId,
    pn.PhoneNumber
FROM    dbo.PhoneNumber pn INNER JOIN dbo.Person o ON pn.PersonId = o.PersonId

and

CREATE VIEW dbo.vw_OrganisationPhoneNumber
AS
SELECT  pn.Id,
    pn.OrganisationId,
    pn.PhoneNumber
FROM    dbo.PhoneNumber pn INNER JOIN dbo.Organisation o ON pn.OrganistionId = o.OrganisationId

Using these views in the mapping as though they were tables enables all the normal CRUD operations while maintaing the original schema, albeit with two extra views.

A compromise certainly but one that I think is probably justifiable when you can't change the table structure of an existing database.

Dan Kennedy