Sunday, July 20, 2008

Linq To Sql and Value Objects

Unfortunately Linq to SQL lacks support for Value Objects. This is a big limitation when you do Domain Driven Design as we do it on a project that I'm currently involved. We didn't use this pattern so far but last week there was no way around it. I had to implement a feature based on the stock of monetary units. I identified an object MonetaryUnitStock that represents the stock for a monetary unit like e.g. 10 Swiss francs. I didn't want to care about identity for that object and I wanted it to be immutable.

For my mentioned feature I had no requirements for querying. So the implementation with Linq to SQL was straight forward. Here is the code in C#.

public struct MonetaryUnitStock: IEquatable<MonetaryUnitStock>
{
private readonly int _numberOfUnit;
private readonly MonetaryUnitType _type;

public MonetaryUnitStock(MonetaryUnitType type, int numberOfUnit)
{
_type = type;
_numberOfUnit = numberOfUnit;
}

public int NumberOfUnit
{
get { return _numberOfUnit; }
}

public MonetaryUnitType MonetaryUnitType
{
get { return _type; }
}

public bool Equals(MonetaryUnitStock other)
{
return MonetaryUnitType.Equals(other.MonetaryUnitType) && this.NumberOfUnit.Equals(other.NumberOfUnit);
}

public override bool Equals(object obj)
{
if(obj is MonetaryUnitStock)
{
return Equals((MonetaryUnitStock)obj);
}
return false;
}


public override int GetHashCode()
{
return MonetaryUnitType.GetHashCode() ^ NumberOfUnit.GetHashCode();
}
}

    partial class MoneyList
{
private MonetaryUnitStock? _monetaryUnitStockUnit100;

public MonetaryUnitStock MonetaryUnitStockUnit100
{
get
{
if (_monetaryUnitStockUnit100 == null)
{
_monetaryUnitStockUnit100 = new MonetaryUnitStock(MonetaryUnitType.Unit100, NumberOfUnit100);
}
return _monetaryUnitStockUnit100.Value;
}
set
{
if(value.MonetaryUnitType != MonetaryUnitType.Unit100)
{
throw new ArgumentException("MonetaryUnitStockUnit100 expects MonetaryUnitType.Unit100");
}
_monetaryUnitStockUnit100 = value;
_NumberOfUnit100 = _monetaryUnitStockUnit100.Value.NumberOfUnit;
}
}
}


I used the DBML designer for creating this simplified example. In the designer I marked the NumberOfUnit100 attribute as private to just provide the Value Object to the outside. So client just can set and get MonetaryUnitStockUnit100 and have no access to the underlying simple type.

The reason that I implemented the MonetaryUnitStockUnit100 Property with lazy loading is, that Linq to SQL provides no interception point when reconstituting an object from persistence. The OnCreated() method generated by the designer is not suitable as it is called before the actual values are set.