views:

165

answers:

2

When calling context.SaveChange(), I get an exception: {"An error occurred while updating the entries. See the InnerException for details."} with an InnerException of "SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM."

Generally this error is pretty easy to fix -- just find the DateTime property whose value was never set (defaulted to MinValue). Unfortunately, I checked all properties on my object, and all of them are set to valid dates/times.

Is there some way to figure out which property EF is referring to when throwing this exception?

Also, I'm only actually checking the object I added to the context right before SaveChanges (and as far as I know, I'm only adding 1). Is there a way to look at all pending data that is about to be saved?

Edit

InnerException.StackTrace:

at System.Data.SqlTypes.SqlDateTime.FromTimeSpan(TimeSpan value)
at System.Data.SqlTypes.SqlDateTime.FromDateTime(DateTime value)
at System.Data.SqlClient.MetaType.FromDateTime(DateTime dateTime, Byte cb)
at System.Data.SqlClient.TdsParser.WriteValue(Object value, MetaType type, Byte scale, Int32 actualLength, Int32 encodingByteSize, Int32 offset, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParser.TdsExecuteRPC(_SqlRPC[] rpcArray, Int32 timeout, Boolean inSchema, SqlNotificationRequest notificationRequest, TdsParserStateObject stateObj, Boolean isCommandProc)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
at System.Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(UpdateTranslator translator, EntityConnection connection, Dictionary`2 identifierValues, List`1 generatedValues)
at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)

Edit 2

It may have to do something with my work flow... For example...

  • I build object SalaryInformation in the class responsible for building Entity objects
  • SalaryInformation has an Employee property on it, but the class that builds it only knows the Employee ID, so it sets SalaryInformation.Employee = new Employee { ID = 1 } (leaving the date fields set to MinValue)
  • I pass the SalaryInformation object into a method to be saved
  • Inside the save method, I look up the Employee object in the database based on the ID and then assign the returned Employee object to SalaryInformation.Employee
  • I then context.AddToSalaryInformation(SalaryInformation) and context.SaveChanges()

I suspect this is leaving a straggler Employee behind in the context with only the ID set, and no Dates, thus the error.

Edit 3

Indeed, workflow was the issue. If I simply say `SalaryInformation.Employee = null;' before assigning the employee object from the database, then the straggler goes away, and no error occurs.

Is this the intended behavior and work around? It seems quite terrible.

+1  A: 

Use the SQL profiler tool and run a trace.

[Edit] You can also try implementing EF tracing as described here.

James
I tried that, but only valid statements show up. Is there some way to configure profiler to show errors?Also, the exception's text leads me to believe that it never actually makes it to SQL. I get "The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value." from SQL when I tried to insert a bad date.", but perhaps ADO.NET captures an error code and provides a friendlier message.
Langdon
Even if the datetime value is out of the acceptable range it would still be a valid SQL statement that should show up as prepared SQL statement with sp_execsql. Using a trace has worked for me before to diagnose these types of issues and I'm pretty sure the error must be coming from SQL server and not the provider. Try checking the SQL server error log too.
James
I think this is an ADO.NET error, not a SQL Server error. There *may* be a SQL statement associated, but it might have been successful.
Craig Stuntz
Check my comment on the original question... I think that's my issue. If I recreate the SalaryInformation object within the method, call AddToSalaryInformation, and SaveChanges, it works fine. Why can't I use the existing object?
Langdon
It's a bit more work, but try my suggestion of using EF tracing(link in my last answer post edit)
James
Hi James, I figured out the issue, but don't understand why it's designed like that. Can you see Edit 2 and 3 above and offer any insight? +1 for effort here (going to bookmark that link for later).
Langdon
+2  A: 

You are setting the employee the wrong way. The simplest way to do this is:

SalaryInformation.Employee = context.Employees.Where(e => e.Id == 1).First();
context.AddToSalaryInformation(SalaryInformation);

That means a DB access.

In EF 4, with FK associations, you can do:

SalaryInformation.EmployeeId = 1;
context.AddToSalaryInformation(SalaryInformation);

In EF 1, a workaround is:

SalaryInformation.EmployeeReference.EntityKey = 
    new EntityKey("MyEntities.Employees", "Id", 1);
context.AddToSalaryInformation(SalaryInformation);

But creating a stub, like you do in your second example, requires additional work.

Craig Stuntz

related questions