12

The entity framework gives me generic messages in the exception without telling me the exact entity and the attribute which caused the error. How do I get more information about the error?

This happens in many cases such as

The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

and

The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value. The statement has been terminated.

Exception details:

[SqlException (0x80131904): The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value. The statement has been terminated.] System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) +404 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() +412 System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +2660 System.Data.SqlClient.SqlDataReader.ConsumeMetaData() +59 System.Data.SqlClient.SqlDataReader.get_MetaData() +118 System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +6431425 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) +6432994 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +538 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +28 System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) +256 System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) +19 System.Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(UpdateTranslator translator, EntityConnection connection, Dictionary2 identifierValues, List1 generatedValues) +270 System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter) +391

[UpdateException: An error occurred while updating the entries. See the inner exception for details.] System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter) +11223976 System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options) +833 System.Data.Entity.Internal.InternalContext.SaveChanges() +218

[DbUpdateException: An error occurred while updating the entries. See the inner exception for details.] System.Data.Entity.Internal.InternalContext.SaveChanges() +291

chadisbad
  • 385
  • 2
  • 4
  • 16
  • How many places are you using a `Datetime2`? Have a read of [this](http://stackoverflow.com/a/1334193/1466627). – Bob. May 03 '13 at 13:40

2 Answers2

11

Here's the code I have in my solution:

try
{
    _context.SaveChanges();
}
catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
{
    Exception raise = dbEx;
    foreach (var validationErrors in dbEx.EntityValidationErrors)
    {
        foreach (var validationError in validationErrors.ValidationErrors)
        {
            string message = string.Format("{0}:{1}", validationErrors.Entry.Entity.ToString(), validationError.ErrorMessage);
            //raise a new exception inserting the current one as the InnerException
            raise = new InvalidOperationException(message , raise);
        }
    }
    throw raise;
}

You can use it as a basis to add into your solution ... it builds a nested set of exceptions with all the details from Entity Framework.

qujck
  • 14,388
  • 4
  • 45
  • 74
  • 1
    I think this is good for the first error, but for the second error I dont get a `DbEntityValidationException` I get this: `[DbUpdateException: An error occurred while updating the entries. See the inner exception for details.]` – chadisbad May 03 '13 at 03:21
  • @chadisbad what does the inner exception say? – qujck May 03 '13 at 08:09
  • 1
    The inner exception is `The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value. The statement has been terminated.` I want to know if I can find out the specific entity and attribute (column) that causes the exception. – chadisbad May 03 '13 at 12:52
  • This catch ecapsulates cuncurrency exceptions? – Santiago Benitez Jul 08 '13 at 15:39
  • @SantiagoBenitez sorry but I don't know how they are handled. It might do and it might not, depending on how the EF presents them. – qujck Jul 08 '13 at 17:47
  • Above solution doesn't work for MySql database. As MySql connector throws Exception of type MySql.Data.MySqlClient.MySqlException . Any Idea what could be done in this case? – Abhijeet Nagre Nov 16 '17 at 08:18
0

You need to write tests for repositories and in the base class for your tests:

try
{
    DbContext.SaveChanges();
}
catch (DbEntityValidationException e)
{
    e.EntityValidationErrors.SelectMany(error => error.ValidationErrors).ToList().ForEach(
    item => Console.WriteLine("{0} - {1}", item.PropertyName, item.ErrorMessage));
    throw;
}
Vlad Omelyanchuk
  • 3,021
  • 7
  • 29
  • 35
  • Above solution doesn't work for MySql database. As MySql connector throws Exception of type MySql.Data.MySqlClient.MySqlException . Any Idea what could be done in this case? – Abhijeet Nagre Nov 16 '17 at 08:18