[c#] How to fix the datetime2 out-of-range conversion error using DbContext and SetInitializer?

I'm using the DbContext and Code First APIs introduced with Entity Framework 4.1.

The data model uses basic data types such as string and DateTime. The only data annotation I'm using in some cases is [Required], but that's not on any of the DateTime properties. Example:

public virtual DateTime Start { get; set; }

The DbContext subclass is also simple and looks like:

public class EventsContext : DbContext
{
    public DbSet<Event> Events { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Event>().ToTable("Events");
    }
}

The initializer sets dates in the model to sensible values in either this year or next year.

However when I run the initializer, I get this error at context.SaveChanges():

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 don't understand why this is happening at all because everything is so simple. I'm also not sure how to fix it since there is no edmx file to edit.

Any ideas?

This question is related to c# .net entity-framework ef-code-first dbcontext

The answer is


In case anyone is as dopey as me, double check the year of your date. I was converting a date from a text file in YYMMDD format so was creating a date with a year of 0020, not 2020. Obvious error but I spent more time looking at it but not seeing it than I should have!


One line fixes this:

modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));

So, in my code, I added:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));
}

Adding that one line to the DBContext subclass override void OnModelCreating section should work.


Based on user @andygjp's answer, its better if you override the base Db.SaveChanges() method and add a function to override any date which does not fall between SqlDateTime.MinValue and SqlDateTime.MaxValue.

Here is the sample code

public class MyDb : DbContext
{
    public override int SaveChanges()
    {
        UpdateDates();
        return base.SaveChanges();
    }

    private void UpdateDates()
    {
        foreach (var change in ChangeTracker.Entries().Where(x => (x.State == EntityState.Added || x.State == EntityState.Modified)))
        {
            var values = change.CurrentValues;
            foreach (var name in values.PropertyNames)
            {
                var value = values[name];
                if (value is DateTime)
                {
                    var date = (DateTime)value;
                    if (date < SqlDateTime.MinValue.Value)
                    {
                        values[name] = SqlDateTime.MinValue.Value;
                    }
                    else if (date > SqlDateTime.MaxValue.Value)
                    {
                        values[name] = SqlDateTime.MaxValue.Value;
                    }
                }
            }
        }
    }
}

Taken from the user @sky-dev's comment on https://stackoverflow.com/a/11297294/9158120


In my case, after some refactoring in EF6, my tests were failing with the same error message as the original poster but my solution had nothing to do with the DateTime fields.

I was just missing a required field when creating the entity. Once I added the missing field, the error went away. My entity does have two DateTime? fields but they weren't the problem.


In some cases, DateTime.MinValue (or equivalenly, default(DateTime)) is used to indicate an unknown value.

This simple extension method can help handle such situations:

public static class DbDateHelper
{
    /// <summary>
    /// Replaces any date before 01.01.1753 with a Nullable of 
    /// DateTime with a value of null.
    /// </summary>
    /// <param name="date">Date to check</param>
    /// <returns>Input date if valid in the DB, or Null if date is 
    /// too early to be DB compatible.</returns>
    public static DateTime? ToNullIfTooEarlyForDb(this DateTime date)
    {
        return (date >= (DateTime) SqlDateTime.MinValue) ? date : (DateTime?)null;
    }
}

Usage:

 DateTime? dateToPassOnToDb = tooEarlyDate.ToNullIfTooEarlyForDb();

In my case this happened when I used entity and the sql table has default value of datetime == getdate(). so what I did to set a value to this field.


My solution was to switch all datetime columns to datetime2, and use datetime2 for any new columns. In other words make EF use datetime2 by default. Add this to the OnModelCreating method on your context:

modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));

That will get all the DateTime and DateTime? properties on all your entities.


Simple. On your code first, set the type of DateTime to DateTime?. So you can work with nullable DateTime type in database. Entity example:

public class Alarme
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        public DateTime? DataDisparado { get; set; }//.This allow you to work with nullable datetime in database.
        public DateTime? DataResolvido { get; set; }//.This allow you to work with nullable datetime in database.
        public long Latencia { get; set; }

        public bool Resolvido { get; set; }

        public int SensorId { get; set; }
        [ForeignKey("SensorId")]
        public virtual Sensor Sensor { get; set; }
    }

I had the same issue and in my case I was setting the date to new DateTime() instead of DateTime.Now


If your DateTime properties are nullable in the database then be sure to use DateTime? for the associated object properties or EF will pass in DateTime.MinValue for unassigned values which is outside of the range of what the SQL datetime type can handle.


initialize the Start property in the constructor

Start = DateTime.Now;

This worked for me when I was trying to add few new fields to the ASP .Net Identity Framework's Users table (AspNetUsers) using Code First. I updated the Class - ApplicationUser in IdentityModels.cs and I added a field lastLogin of type DateTime.

public class ApplicationUser : IdentityUser
    {
        public ApplicationUser()
        {
            CreatedOn = DateTime.Now;
            LastPassUpdate = DateTime.Now;
            LastLogin = DateTime.Now;
        }
        public String FirstName { get; set; }
        public String MiddleName { get; set; }
        public String LastName { get; set; }
        public String EmailId { get; set; }
        public String ContactNo { get; set; }
        public String HintQuestion { get; set; }
        public String HintAnswer { get; set; }
        public Boolean IsUserActive { get; set; }

        //Auditing Fields
        public DateTime CreatedOn { get; set; }
        public DateTime LastPassUpdate { get; set; }
        public DateTime LastLogin { get; set; }
    }

Even though this question is quite old and there are great answers already, I thought I should put one more which explains 3 different approaches to solve this problem.

1st Approach

Explicitly map DateTime property public virtual DateTime Start { get; set; } to datetime2 in corresponding column in the table. Because by default EF will map it to datetime.

This can be done by fluent API or data annotation.

  1. Fluent API

    In DbContext class overide OnModelCreating and configure property Start (for explanation reasons it's a property of EntityClass class).

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //Configure only one property 
        modelBuilder.Entity<EntityClass>()
            .Property(e => e.Start)
            .HasColumnType("datetime2");
    
       //or configure all DateTime Preperties globally(EF 6 and Above)
        modelBuilder.Properties<DateTime>()
            .Configure(c => c.HasColumnType("datetime2"));
    }
    
  2. Data annotation

    [Column(TypeName="datetime2")]
    public virtual DateTime Start { get; set; }
    

2nd Approach

Initialize Start to a default value in EntityClass constructor.This is good as if for some reason the value of Start is not set before saving the entity into the database start will always have a default value. Make sure default value is greater than or equal to SqlDateTime.MinValue ( from January 1, 1753 to December 31, 9999)

public class EntityClass
{
    public EntityClass()
    {
        Start= DateTime.Now;
    }
    public DateTime Start{ get; set; }
}

3rd Approach

Make Start to be of type nullable DateTime -note ? after DateTime-

public virtual DateTime? Start { get; set; }

For more explanation read this post


You can make the field nullable, if that suits your specific modeling concerns. A null date won't be coerced to a date that isn't within the range of the SQL DateTime type the way a default value would. Another option is to explicitly map to a different type, perhaps with,

.HasColumnType("datetime2")

I'm using Database First and when this error happened to me my solution was to force ProviderManifestToken="2005" in edmx file (making the models compatible with SQL Server 2005). Don't know if something similar is possible for Code First.


Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to .net

You must add a reference to assembly 'netstandard, Version=2.0.0.0 How to use Bootstrap 4 in ASP.NET Core No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization .net Core 2.0 - Package was restored using .NetFramework 4.6.1 instead of target framework .netCore 2.0. The package may not be fully compatible Update .NET web service to use TLS 1.2 EF Core add-migration Build Failed What is the difference between .NET Core and .NET Standard Class Library project types? Visual Studio 2017 - Could not load file or assembly 'System.Runtime, Version=4.1.0.0' or one of its dependencies Nuget connection attempt failed "Unable to load the service index for source" Token based authentication in Web API without any user interface

Examples related to entity-framework

Entity Framework Core: A second operation started on this context before a previous operation completed EF Core add-migration Build Failed Entity Framework Core add unique constraint code-first 'No database provider has been configured for this DbContext' on SignInManager.PasswordSignInAsync The instance of entity type cannot be tracked because another instance of this type with the same key is already being tracked Auto-increment on partial primary key with Entity Framework Core Working with SQL views in Entity Framework Core How can I make my string property nullable? Lazy Loading vs Eager Loading How to add/update child entities when updating a parent entity in EF

Examples related to ef-code-first

EntityType 'IdentityUserLogin' has no key defined. Define the key for this EntityType There is already an object named in the database The entity type <type> is not part of the model for the current context Entity Framework 6 Code first Default value Unique Key constraints for multiple columns in Entity Framework Entity Framework (EF) Code First Cascade Delete for One-to-Zero-or-One relationship Introducing FOREIGN KEY constraint may cause cycles or multiple cascade paths - why? How to delete and recreate from scratch an existing EF Code First database Entity Framework: One Database, Multiple DbContexts. Is this a bad idea? Ignoring a class property in Entity Framework 4.1 Code First

Examples related to dbcontext

The entity type <type> is not part of the model for the current context Entity Framework: One Database, Multiple DbContexts. Is this a bad idea? One DbContext per web request... why? How to fix the datetime2 out-of-range conversion error using DbContext and SetInitializer? How to update only one field using Entity Framework?