I found a great little bug in Entity Framework this morning. One of their exception handlers can throw an exception, that hides the true exception. Here’s how to recreate this:
- Set your thread culture to a neutral culture: i.e. ‘en’ instead of ‘en-US’
- Create a new EF Context
- Find an object (A) that has a dependency to another object (B) via foreign key and B has a dependency to object C via another foreign key.
- Create a new object of type A called ‘a’
- Get object B and detach it from the database (as if you were getting it in via a web service call). B should lose it’s link to C
- Add object B to A
- Attempt to add A to the database via the context.AddToA(a)
- Call context.SaveChanges().
What you should get is
System.Data.Entity Type: System.Data.UpdateException Message: Entities in '[contextName].B partticipate in the 'FK_B_C' relationship. 0 related 'C' were found. 1 'C' is expected.
What you will get is:
System.NotSupportedException: Culture 'en' is a neutral culture. It cannot be used in formatting and parsing and therefore cannot be set as the thread's current culture. at System.Globalization.CultureInfo.CheckNeutral(CultureInfo culture) at System.Globalization.CultureInfo.get_NumberFormat() at System.Globalization.NumberFormatInfo.GetInstance(IFormatProvider formatProvider) at System.Data.EntityUtil.ConvertCardinalityToString(Nullable`1 cardinality) at System.Data.EntityUtil.UpdateRelationshipCardinalityConstraintViolation(String relationshipSetName, Int32 minimumCount, Nullable`1 maximumCount, String entitySetName, Int32 actualCount, String otherEndPluralName, IEntityStateEntry stateEntry) at System.Data.Mapping.Update.Internal.UpdateTranslator.RelationshipConstraintValidator.ValidateConstraints() at System.Data.Mapping.Update.Internal.UpdateTranslator.ProduceCommands() at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter) at System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache) at System.Data.Objects.ObjectContext.SaveChanges(Boolean acceptChangesDuringSave) at System.Data.Objects.ObjectContext.SaveChanges()
The only way to get the real error, is to change your current culture from a neutral to a specific culture. I’ve never seen this one before, and I had a few minutes of head scratching before we got the real cause.