Tuesday, November 19, 2013

Resolve Entity Framework “An error occurred while saving entities that do not expose foreign key properties for their relationships” exception due to an empty string

A more complete version of the error message is this:

System.Data.Entity.Infrastructure.DbUpdateException: An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details. System.Data.UpdateException: An error occurred while updating the entries. See the inner exception for details. System.Data.SqlClient.SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_xxx". The conflict occurred in database "xxx", table "dbo.xxx", column ‘xxx’. The statement has been terminated.

My POCO originally had this design, exposing the Race string property as the foreign key for the associated RaceEntity lookup table entity:

  1. public string Race { get; set; }
  2. public virtual RaceLookup RaceEntity { get; set; }

My configuration file looks like this:

  1. HasOptional(m => m.RaceEntity).WithMany().HasForeignKey(m => m.Race);

The underlying SQL Server table has a Race column defined as nullable nvarchar(50) with a foreign key constraint to a related Races lookup table.

In the UI, I have a dropdown list containing all of the possible Race values from the Races lookup table, with an additional lookup value of “None” because the underlying table allows a null value.  I was getting the exception when a user selected the “None” value because that set my POCO.Race string property to equal an empty string, which in turn caused the foreign key constraint conflict exception.

The solution was to change my code so that all empty strings are converted to null prior to save.  In my case, I accomplished this by changing the design of the Race property on my POCO:

  1. private string _race;
  2. public string Race
  3. {
  4.     get { return _race; }
  5.     set { _race = string.IsNullOrEmpty(value) ? null : value; }
  6. }
  7. public virtual RaceLookup RaceEntity { get; set; }