Chris Klepeis
Chris Klepeis

Reputation: 9973

Fluent NHibernate Mapping (one to one with conditional)

I'm trying to "clean" a poorly designed database structure (at least in my ORM).

The table structure is something like this:

Table: Members
memberID (int PK)
username (varchar)

Table: Addresses
addressID (int PK)
memberID (int, not set as a FK - awesome)
firstName (varchar)
lastName (varchar)
addressLine1 (varchar)
isBillingAddress (bit)

So I created 2 classes (entities), one for a customer and one for an address.

public class Customer
{
    public virtual int CustomerID { get; set; }
    public virtual string FirstName
    {
        get { return BillingAddress.FirstName; }
        set { BillingAddress.FirstName = value; }
    }
    public virtual string LastName
    {
        get { return BillingAddress.LastName; }
        set { BillingAddress.LastName = value; }
    }
    public virtual Address BillingAddress { get; set; }
    public virtual Address ShippingAddress { get; set; }
}

public class Address
{
    public virtual Customer Customer { get; set; }
    public virtual int AddressID { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual string AddressLine1 { get; set; }
    public virtual string AddressLine2 { get; set; }
    public virtual string City { get; set; }
    public virtual string State { get; set; }
    public virtual string PostalCode { get; set; }
}

The query to retrieve a customers billing address would be:

SELECT TOP 1 *
FROM dbo.Address
WHERE isBilling = 1
AND memberID = @memberID

There should only 1 billing and shipping address per customer. So far, my fluent classmap looks like this:

public class CustomerMapping : ClassMap<Customer>
{
    public CustomerMapping()
    {
        Table("Members");

        Id(m => m.CustomerID).Column("memberID");
        Map(m => m.BillingAddress);

        HasOne(x => x.BillingAddress).PropertyRef("memberID");
        HasOne(x => x.ShippingAddress).PropertyRef("memberID");
    }
}

I'm not sure if I should even be using HasOne... it should be a one to one mapping. How can I get the "where" clause in there (I.E. WHERE Address.memberID = Members.customerID) to distinguish between billing and shipping? Also, what about top 1? I know I can maybe use Join but I dont see a fluent function to add the where clause.

Modifying the database structure is unfortunately not an option.

Thanks

Upvotes: 1

Views: 936

Answers (1)

James Kovacs
James Kovacs

Reputation: 11651

You don't want a HasOne(), though it sounds right. HasOne() means that the tables share primary keys. Use References() instead.

Upvotes: 1

Related Questions