DDD - Part Two - Value Object Persistence
In DDD, the value object is used when your entity conceptually does not have an identity and it is all about the data. Now the question of something being a value object or an entity - where we care about the actual Id - is a business question but think about an address in a ordering management system where a customer has addresses. You probably don’t care about the address as something on its own, so you don’t care about it’s identity and as such, two addresses are the same if their values are the same. Another away about the value object, is that it is immutable, meaning if you want to change an address, you need to create a new one and replace an existing address as it is not possible to change an existing address.
Now ORMs in general are not happy with these approach as they mostly rely on tables and Ids to store objects. To map these objects and store them in our database there are two scenarios: Storing an entity with a value object that’s not a collection and Storing it with a collection of value objects.
Taking a Customer and an Address as the example, from the domain perspective, it’d look like this:
public class Address
Reiterating that we don’t care about the Id, it’d make sense to store this somewhere where we don’t need an Id. If you’re using EntityFramework, it is not possible to store the ‘entity’ (as in an object that’s stored in the database table) without having an ID. If you try to store the address in its own table, you still need an Id and custom mapping (we’ll get to this in a minute), otherwise as in the example above, you can store it as a part of the Customer. To achieve this you’ll need to register your value object as a complex type either by using the
[ComplexType] attribute or like this:
public class MyDataContext : DbContext
Now when you store a Customer, Address properties are stored as fields in the customer table, e.g. Customer table would have fields such as Postal_Street, Postal_StreetType and Mailing_Street, Mailing_StreetType, etc.
The ComplexTypes come with a caveat: They can not be null. You’ll have to new up all the complex type in your constructor. So if they can not be null - much like how an Struct would behave - how would you describe the lack of a value?
In value object world, what does it mean to not have a value? Specially if you use Structs, there’s no way to have a null value object. In fact when your value objects are not a collection, EntityFramework would not let you store them as null (where as all the value object fields are set to null). To work around this you can use Null Object pattern. A customer who doesn’t have a mailing address would be constructed like this:
var postalAddress = new Address(blah blah);
and under the hood, the Null static method would just return a new object, so to make EF happy. This is kind of the same as how ‘Empty’ or lack of value is express across .NET platform (remember String.Empty?), the complete implementation of the address class would be like this:
public class Address
If you need to check the null object being null or not, you can achieve it by checking all the fields being set to null. It may not be ideal, but the question you probably ask yourself if you are doing it is that if the thing you are modelling is a even a value object?
You might ask, what’s the private constructor for? Turns out, EntityFramework needs a parameterless constructor when it hydrates the object from the database. It does not have to be public though, so having it as private helps to encapsulate the entity/value objects.
When you have a collection of value objects things are different. You can’t store them as a part of your entity and you have to store them in a joined table. Take a look at this example:
public class Customer
Here, the addresses should be stored in a separate joined table, while conceptually we don’t care about such a thing as PrimaryKey for our collection of value objects. Our lives would have been much easier if we were using a document database, or a more extensible ORM like NHibernate but in EntityFramework it is not possible to have a table with no PrimaryKey.
The dilemma here is that you want to have your Id for the value object private, since that’s just an implementation detail, but still for mapping and persistence purpose you need to expose it. So if we’re going to store our Address as a collection, this code snippet wouldn’t work:
public class Address
Although you’ll get a compilation error with this code, there are couple of things to note. If you look close enough, we no longer register our address as a ComplexType, but rather as an entity (sigh) but since you will not directly access a value object, we’re not exposing it on the DataContext. The other thing is that we need a way of configuring that Id property to be auto-generated. Since the code does not compile, how do we make it work? There are two ways of fixing this. One way would be to moving that Id into a base class and exposing it so that we can do our mapping (yuck!) and the other way is to move the configuration/mapping code into our entity/value object so that they can access the private property (yuck!). Since there’s no proper solution to this Both workarounds left something to be desired but see which one works for you and pick one.
You still need to generate a unique key for that PrimaryKey but since you don’t care, you can use what your database gives you like Sequence or Identity. On next posts we’ll see which ID generation strategy works better with EntityFramework.