As I burn my mid-night oil, trying to wrap my head around implementation strategy for Value Objects using Entity Framework, it so turns out that with Entity framework’s fluent API, it is ridiculously easy to do the same. But before we look at the implementation details of Value Objects using Entity Framework, let’s have few words about value objects.
Value Objects are small objects with no identity. Their values represent their identity. Hence, two Value Objects with equal fields are considered to be equal. Value Objects should be Immutable.
Let’s consider a Value Object called ProductPrice.
public class ProductPrice { public double Amount { set; get; } public string Currency { set; get; } }
Since we would like our value object to be Immutable, we will make the properties read-only and set them during the construction.
public class ProductPrice { public ProductPrice(double amount, string currency) { this.Amount = amount; this.Currency = currency; } public double Amount { private set; get; } public string Currency { private set; get; } }
As the name suggests, ProductPrice represents the price of the Product.
public class Product: IEntity { public Guid Id { get; set; } public string Name { get; set; } public Price Price { get; set; } public Guid CategoryId { get; set; } }
Since the product has only one price, it would make sense to have a single table for them. In order to do so, add the following in the DBContext,
public DbSet<Product> Products { get; set; }
Entity Framework will generate one table for you called Products with the following columns
- Id
- Name
- CategoryId
- Price_Amount
- Price_Currency
With fluent configuration you can change the name of the columns, if you don’t like them. For example, I preffer ‘PriceAmount’ over ‘Price_Amount’, hence, I did the following to configuration to change the column name.
public ProductMap() { Property(a => a.Price.Amount).HasColumnName("PriceAmount"); }
And in the DBContext class add the following,
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new ProductMap()); }
And there you go. Simple, isn’t it?