How to work with Value Object In C#
Posted on: 2014-08-19
Implementing value objects in your project is something that every software has to do. It may sounds like a simple task but from my experience I can tell you that it is less easier than it looks like. In fact, it is easy but developer does not really understand the difference between an enum, a entity or a value object.
A value object is a class that has information that does not have a unique identifier for every usage but a unique identifier for the instance itself. A value object are reused across your application many times which remove a lot of complexity that you would have by having a unique identity for each of these instance. For example, if you have a Person class that has a relationship status. This is the perfect example for value object. You create a class for every of your status like one for "Married" and one for "Single". You could have a Married entry for each person but that would result to a lot of duplicate. You could have used a C# enum or a C# constant but this would result to a weak integrity between your classes and also in your persistence storage. The integrity is weak in the code because you would pass between methods string or enum which could be casted from integer. The string could be anything and would require a lot of validations. In the database, you save in a column a string or an integer (for the enum). In both case, you do not have any validation. This is where value object can shine. You can have a strong integrity in code but also in the database. You can also have a big performance saving by having the same object reused across the application. For example, if you have 1 million Person that are single, 1 million will be linked to the same object. You do not have redundancy.
Before going any deeper, let's examine a second example that is from Eric Evans in his book Domain Driven Design. Imagine, a box of markers with different colors. Each marker will have a value object that define the color. Each color does not have a different id for each marker, neither have a different id for each lines drawn. You would have simply the class Marker having a reference to the value object that define the color. You also have for each Line class a reference to the value object color to know the color of the line. In both case, it would be too big in resource to save a new entity for each Markers and Lines.
Another example could be with a simple state that change between Active, Inactive, NotSet. Those three states can use value object to define the state of any entity that require to have a state defined. Or another example could be that you have several currencies that you want to handle in your program. Every amount is set to a currency. The list is well defined and do not change dynamically so you can create a class by currency. This is crucial to have your value object not dynamic. It is the cost of this pattern. You cannot have something dynamic because you need to have the value object defined in code, in a class.
The image above shows that we have a value object named "CurrencyType". This mean that if you have a class that has a CurrencyType property.
public void Money { public CurrencyType Currency { get; set; } public decimal Amount { get; set; } }
This usage is very strong because you can only assign a CurrencyType. It would be weak to have used a string for the currency like the code below.
public void Money { public string CurrencyType { get; set; } public decimal Amount { get; set; } }
The problem is the same for an integer is assigned. The Money class could have used an enum but at the time of saving everything, the table would have the decimal value for the amount and an integer for the currency type. The problem is now at the database level where the integer could been altered and when loaded back in the software would cause instability. However, the value object could not be unstabilized because of the database integrity. Since every value object are reflected by a table with entries, those entries are referenced by a foreign key to the one that use the value object.
For example, if you have an Item that has a price of type Money, you could set the CurrencyType to USD. In the database, the table Item would have a column price and a column currency type. The currency type would have a foreign key to the table currency type.
Every values of the value object is a class. For example, if you have a Canadian currency and an American currency you need two classes.
public class CanadianCurrency:CurrencyType { public CanadianCurrency() { base.Id = 1; base.Name = "$CDN"; base.Culture = new CultureInfo("fr-CA"); } }
public class USACurrency:CurrencyType { public USACurrency() { base.Id = 2; base.Name = "$USD"; base.Culture = new CultureInfo("en-US"); } }
You can have anything you want in the value object. The minimum is to have a identifier that will be the primary key in the database. In the example above, it is an integer but could be a string. The important thing is to have all your implementation to inherit the same class. In that case, it is CurrencyType.
public abstract class CurrencyType : ValueObject<CurrencyType> { public static readonly CurrencyType Canada = new CanadianCurrency(); public static readonly CurrencyType UnitedStatesOfAmerica = new USACurrency(); }
The two static property act as a factory and are not required. It is just easy to select values because instead of instantiate yourself the entity your use the factory which offer all possibles choice with Microsoft Intellisense.
//Instead of : item.CurrencyType = new CanadianCurrency(); //Use : item.CurrencyType = CurrencyType.Canada;
You do not have to inherit to ValueObject like in the example above, but if you do, it will give you some additional possibility like having automatic parsing from primary value (integer in our example but could have been string) to the value object. Imagine a scenario where you let the user choose from a combox box the value object. The value is returned as the unique identifier. In the case of the money currency, the value 2 could be returned to the controller and you have from this value get back the value object into the model object. This can be done by a method that map the id to the value object.
public abstract class ValueObject : IEntity { public int Id { get; set; } public string Name { get; set; }
public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } if (ReferenceEquals(this, obj)) { return true; } if (obj.GetType() != this.GetType()) { return false; } return Equals((ValueObject) obj); } protected bool Equals(ValueObject other) { return Id == other.Id; }
public override int GetHashCode() { return Id; }
public static bool operator ==(ValueObject left, ValueObject right) { return Equals(left, right); }
public static bool operator !=(ValueObject left, ValueObject right) { return !Equals(left, right); } }
public abstract class ValueObject<TValueObject> : ValueObject where TValueObject : IEntity { public static TValueObject GetFromId(int value) { Type type = typeof(TValueObject);
var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static); foreach (var field in fields) { var fieldValue = (TValueObject) field.GetValue(null); if (fieldValue.Id == value) { return fieldValue; } } throw new KeyNotFoundException(string.Concat(value, "cannot be found in any static fields.")); } }
It may look like a lot of code but it is not. The first class that is not generic only override some operator to simplify the comparison between value object of the same type. The generic version give the possibility to get from the the id the value object. It uses reflection to get for each implementation of the value object type if one has the Id passed by parameter.
item.CurrencyType = CurrencyType.GetFromId(viewModel.CurrencyIdFromWebForm);
This pattern works very well with Entity Framework.
public class CurrencyTypeConfiguration : ValueObjectConfiguration<CurrencyType> { public CurrencyTypeConfiguration() { } }
The configuration is very similar to every of your value object. The trick is all in the inherited class, ValueObjectConfiguration that take the type in its generic parameter.
public abstract class ValueObjectConfiguration<T> : EntityTypeConfiguration<T> where T : ValueObject { protected ValueObjectConfiguration() { Map(a => a.MapInheritedProperties()); HasKey(p => p.Id); ToTable(typeof(T).Name, Constants.SchemaNames.ValueObject); } }
The configuration set the inheritance to MapInheritedProperties. This create a single table with all classes. This mean that all value of your value object are in a single table named by the name of the generic class name. In our example, the table created by Entity Framework is named CurrencyType and has two entries. One with ID 1 and one with ID 2.
As you can see in the code and also in the screen shot of the table, a primary key is created. This ensure that you have a unique value object identifier but also that if you use the value object into another entity that this one is strongly referenced.
One more thing. This is very efficient in term of performance. If you have your Item, you do not need to load from the database the currency information. First, because you can have the Id directly from the entity that use the value object. This is because the foreign key is already in the table that use the value object. You only need to load if you have created a lot of data that is not stored in the class but since it is a value object all this information is already in the class. Second, because you can load the whole value object from the method we have defined in the ValueObject class. A trick is to never include/load the value object but to use the method to get back the whole object.
public class Item { public int CurrencyTypeId { get { return this.Currency.Id; } set { this.Currency = CurrencyType.GetFromId(value); } }
/// <summary> /// This is ignored by EntityFramework /// </summary> public CurrencyType Currency { get; set; } }
The code above show a way to do it. You can tell Entity Framework to ignore property and use the CurrentyTypeId. This way, it load and save only the unique identifier and allows you to use the value object property in your business logic. As you can see, the setter of the currency type set the value object value from the GetFromId. The getter also does not link to a integer but to the currency value object. This guarantee us to use the simplest way to save value to entity (by having the foreign key in the class) and to have integrity in the value because it pass through GetFromId() method that thrown an exception if the value is not valid.
The last example is good in the scenario where you have an Entity Framework Complex Object. Complex Object cannot have a navigability association. But, if you have a normal entity, than the best is to have the foreign key in the database. If we also want to have the performance, this mean that we do not want to load the value object object with an Include (to avoid join). To be able to have performance and integrity the best is to have the entity use scalar property that hold the foreign key.
Full Working Version of Value Object
We have discuss about few way to implements value object. Let's warp up everything in a small console application. This final version works for every situation. This mean that it works with required attribute, work by setting the property to null and having a scalar property to the value object, it also work without having to use Include statement to reduce the amount of join and finally, it can use Entity Framework when saving to avoid adding the value object but just referring to it.
First of all, let's define our context. The context define the connection string and remove everything in the configuration about lazy loading, detection and proxy. It also setup 2 entities. The first one is Parent and the second one is Child. A Child will have a reference to a Parent. The Child is referencing a Parent which simulate the "value object".
public class MyContext : DbContext { public MyContext() : base("MyContextConnectionString") { base.Configuration.LazyLoadingEnabled = false; base.Configuration.AutoDetectChangesEnabled = false; base.Configuration.ProxyCreationEnabled = false; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<Parent>(); modelBuilder.Entity<Child>(); } }
The Parent, simulating the value object, has a unique identifier, ID, and a name. It also has the "Create" method which is, in fact, the method that we would use to get the value object. It is the method that we have previously named "GetFromId". This time, we make it very simple for the purpose of the example.
public class Parent { public int Id { get; set; } public string NameParent { get; set; }
public static Parent Create(int id) { return new Parent { Id = id }; } }
The Child class, the one that has the value object, the Parent in this example, is more complex. First of all, we do not use auto-property. This time, we are using properties and fields. One for the class and one for the scalar that represent the foreign key. We do want that to not have to include (create a SQL Join) everytime. TheOnlyParent property return the field directly. That mean that if the field is Null that we will have Null as value. This is what we want for Entity Framework to only save back the Id and not to verify if it has a match with the property. The Child class also has the scalar property that return the field but as something special in the setter to create the object from the method of the value object that can create the value object by its ID.
public class Child { private Parent theOnlyParent; private int theOnlyParentId; public int Id { get; set; } public string NameChild { get; set; } [Required] public Parent TheOnlyParent { get { return theOnlyParent; } set { theOnlyParent = value; if (value != null) TheOnlyParentId = value.Id; } }
public int TheOnlyParentId { get { return theOnlyParentId; } set { theOnlyParentId = value; theOnlyParent = Parent.Create(value); } } }
To be very bulletproof with Entity and this scenario of having a reference to an existing object, let's add a Required attribute into the property field. This mean that Entity will verify if this property is set. That is also mean that setting to Null will raise a validation exception. This is why, every value object (or any entity that link an existing entity) must be set to unchanged.
static void Main(string[] args) { Console.WriteLine("Start create database"); Database.SetInitializer(new DropCreateDatabaseAlways<MyContext>()); Console.WriteLine("Start adding Parent"); var p1 = new Parent {NameParent = "Test Parent Name#1"}; int parentCreatedId; Console.WriteLine("Context"); using (var context = new MyContext()) { context.Set<Parent>().Add(p1); context.SaveChanges(); parentCreatedId = p1.Id; } Console.WriteLine("Start adding a child from a different context"); var c1 = new Child { NameChild= "Child #1" }; c1.TheOnlyParentId = parentCreatedId; c1.TheOnlyParent = new Parent {Id = parentCreatedId}; Console.WriteLine("Context"); using (var context = new MyContext()) { Console.WriteLine("*Change State Child"); context.Entry(c1).State = EntityState.Added; Console.WriteLine("*Change State Child->Parent Navigability Property"); context.Entry(c1.TheOnlyParent).State = EntityState.Unchanged; // We do not want to create but reuse Console.WriteLine("*Save Changes"); context.SaveChanges(); } Console.WriteLine("End"); Console.ReadLine(); }
This code runs without a problem. The property can be set OR can be null and in both case, the association is created in the database. This code as a strong integrity by having the foreign key created but also is aim for performance with the possibility to load the entity (for example Child) without having to include the associate entity (the Parent).
Finally, value object is a simple pattern that should not be a nightmare to implement in your project. If well designed, it can be very easy to use. Entity Framework works very well with value object and performance are as fast as any other solution.