Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Null value objects in NHibernate

I have a person entity containing an Address as a value object:

public Person()
{
    WithTable("Person");
    Id(x => x.Id);
    Component<Address>(x => x.Address, a =>
    {
        a.Map(x => x.Address1);
        a.Map(x => x.Address2);
        a.Map(x => x.Address3);
        a.Map(x => x.Town);
        a.Map(x => x.Postcode);
    });
}

It states in the NHibernate docs that if all the properties of a value object (Address1, Address2 etc) are null, the entire component will be mapped as null (i.e. Person.Address will be null). This is giving me problems in cases where all address fields are null because in my pages where I might have (I'm doing ASP MVC):

<%= Html.TextBoxFor((x => x.Address.Address1))%>

This breaks with a null reference exception. So I'm looking for a clean way to set Address as a new Address() object rather than null if all the fields are empty when I load a Person from the database without doing it manually. I've discounted the following ideas:

Doing null checking in my view (yuk, horrible)

Making database fields not-nullable (I'm dealing with a legacy database)

Anyone any ideas?

like image 328
James Allen Avatar asked Mar 25 '09 16:03

James Allen


2 Answers

Thanks to James' ideas (see his answer and comments) I have modified the Address property of my Person entity from:

public virtual string Address { get; set; }

to:

private Address _address;
public virtual Address Address
{
    get { return _address ?? new Address(); }
    set { _address = value; }
}

This has solved my problem, it works, and it seems to work with NHibernate. Yey!

like image 198
James Allen Avatar answered Nov 12 '22 15:11

James Allen


I don't have any definitive answers creating a method/property accessor that isn't mapped, and that returns a default/null-object if the actual address is null.

public Address GetAddressOrDefault()
{
  return Address ?? new NullAddress();
}

Or similar to the first, create a wrapper for your Address that you use in the view.

public class AddressViewData
{
  private Address address;

  public AddressViewData(Address address)
  {
    this.address = address ?? new NullAddress();
  }

  // expose all address properties as pass-throughs
  public string Street
  {
    get { return address.Street; }
  }
}
like image 28
James Gregory Avatar answered Nov 12 '22 15:11

James Gregory