Thursday, January 7, 2010

Bug in Entity Framework

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:

  1. Set your thread culture to a neutral culture:  i.e. ‘en’ instead of ‘en-US’
  2. Create a new EF Context
  3. 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.
  4. Create a new object of type A called ‘a’
  5. 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
  6. Add object B to A
  7. Attempt to add A to the database via the context.AddToA(a)
  8. 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.

2 comments:

Jeff Derstadt said...

Thanks for bringing this up. To make sure we've got this issue fixed for the upcoming release of .NET 4.0, I tried this using a pre-release version of the Entity Framework in .NET and was not able to repro the exception when I used the "en" CultureInfo so I believe we have it fixed. To confirm, were you using .NET 3.5 SP1?

Thanks again for the report and the blog.

JB said...

Yes, this bug was in .NET 3.5 SP1. I should have mentioned that in the blog. Thanks for checking on this, Jeff.