I have a problem with entity framework. Especially I can not do insert or update operation. Error message:
An error occurred while updating the entries. See the inner exception for details.System.Data.SqlClient.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.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
at System.Data.SqlClient.SqlDataReader.get_MetaData()
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExec开发者_如何转开发uteReader(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)
Can you help me?
Sample code:
ProductGroups group;
if (txtProductGroupName.Text.Trim() != null)
{
group = new ProductGroups();
group.ProductGroupName = txtProductGroupName.Text.Trim();
context.ProductGroups.AddObject(group);
context.SaveChanges();
context.AcceptAllChanges();
lblState.ForeColor = Color.Red;
lblState.Text = "Ürün grubu kaydedildi...";
}
else
{
lblState.ForeColor = Color.Red;
lblState.Text = "Ürün grubu ismini bos geçmeyiniz";
}
The ProductGroups table is defined with 5 columns:
- [ProductGroupID] int
- [ProductGroupName] varchar(100)
- [ProductGroupComment] varchar(1000)
- [CreatedOn] datetime
- [DeletedOn] datetime
You are not filling CreatedOn
and DeletedOn
datas in your added group instance. EF probably sent default .NET value which is 1/1/0001. It resulted in exception because SQL min allowed value for DATETIME
column is 1/1/1753. Either fill value in your code or use DATETIME2
in database.
Look this post please. It can be useful for you - Using sql date data type and EF4.
Adding to BenSwayne's answer:
If you're updated entity is not coming from the database, you will have to tell entity framework to not update the CreatedOn property. To do this, update the code with the following:
if (entry.State == EntityState.Added)
{
e.CreatedOn = currentTime;
}
else
{
// handle updates of objects not originating from the database
var objectStateManager = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager;
ObjectStateEntry entryToUpdate = objectStateManager.GetObjectStateEntry(entry.Entity);
entryToUpdate.RejectPropertyChanges("CreatedOn");
}
While the current answers explain why you encounter this error, no one has suggested a solution or best practice.
The most correct answer here is that you should either make your date fields nullable in the model, or provide a value during all inserts!
There is no need for you to use the DateTime2 datatype, that is just extra overhead and doesn't solve the problem. And you certainly don't want server generated default values for either of those fields.
I would suggest that CreatedOn should be set during inserts and DeletedOn should be nullable.
A neat thing to note is that the entity framework DbContext provides a SaveChanges() method that you can override in your context class. You can use this method to intercept EF saves and insert data such as the audit fields. I have a model base class which contains all of the common audit data like CreatedOn that all my models inherit from. Then I can update the audit dates for any record in my context like this (using EF 4.3 DbContext):
public override int SaveChanges()
{
var currentTime = DateTime.UtcNow;
foreach (var entry in ChangeTracker.Entries<Models.Abstract.ModelBase>())
{
// If this is a new entity add to the Db set the CreatedOn field to now
if (entry.State == EntityState.Added)
{
entry.Entity.CreatedOn = currentTime;
}
// Always set the modified by/on
entry.Entity.ModifiedOn = currentTime;
}
return base.SaveChanges();
}
精彩评论