Entity Framework Does Not Allow To Have Nullable Complex Type
Posted on: 2014-11-12
Once in a while, I forgot that weakness of Entity Framework that make me change the design of my database. Entity Framework (well for the 6 first version at least) cannot save an entity that has a complex type
to null.
Let's get in the context that you have a class named Order, and this one have a Price property. The Price property is of type Money which is a complex type. You cannot set your Price property to null without having Entity Framework crash during the commit phase.
DbUpdateException: Null value for non-nullable member. Member: 'PriceLimit'.
Once you realize that Entity Framework will not help you in this path, you have to change your design. Their are multiple ways to handle this kind of scenario but one that I prefer and I really think is quite easy is to have an additional property inside the complex class that specify is the complex class is null or not. Of course, this would be more clean not to have that property, but at least, it is a viable solution if you own the complex type. It has also the advantage to be cohesive and to not alter all of your classes that use that complex type.
In the complex class we change the value to be nullable now.
private decimal? value;
public decimal? Value { get { return value; } set { this.value = value; } }
This is the first change that will let the database to save null value not to the complex type but to the value of this one. The next step is to create a new property that will specify if the complex type is null or not.
public bool IsNull { get { return !this.Value.HasValue; } set { if (value) { this.Value = null; } else { this.Value = default(decimal); } } }
As you can see, the IsNull property does not contain a value but is calculated on the fly. We also will not store this value in the database. This mean that we need to ignore this property for Entity Framework.
public MoneyConfiguration() { this.Ignore(d => d.IsNull); // Required because Entity Framework cannot have two properties that load the same property(value) }
The reason is double. First, we do not need to save this value because we can calculate it on the fly. Second, Entity Framework does not allow us to read this type of property. Indeed, Entity Framework can save both value (the value and the IsNull flag) but when this one will try to load the data from the database, it will not be able to resolve the value correctly. Primary because both property depend of each other. When setting the Value, the IsNull does not change, so it is fine. However, when Entity Framework set IsNull to false the default value is set. Since we cannot tell Entity Framework to avoid loading a single property or that we cannot specify the order of the properties to be loaded, it is better to avoid having to save the value.