如何使用DbContext和SetInitializer修复datetime2超出范围的转换错误?

我正在使用entity framework4.1中引入的DbContext和Code First API。

数据模型使用基本数据types,如stringDateTime 。 我在某些情况下使用的唯一数据注释是[Required] ,但这不在任何DateTime属性中。 例:

 public virtual DateTime Start { get; set; } 

DbContext子类也很简单,如下所示:

 public class EventsContext : DbContext { public DbSet<Event> Events { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Event>().ToTable("Events"); } } 

初始化程序将模型中的date设置为今年或明年的明智值。

但是,当我运行初始化,我得到这个错误在context.SaveChanges()

将datetime2数据types转换为date时间数据types会导致超出范围的值。 该语句已终止。

我不明白为什么会发生这种情况,因为一切都很简单。 我也不知道如何解决这个问题,因为没有edmx文件来编辑。

有任何想法吗?

您必须确保Start大于或等于SqlDateTime.MinValue(1753年1月1日) – 默认情况下,Start等于DateTime.MinValue(0001年1月1日)。

简单。 在您的代码中,将DateTime的types设置为DateTime ?. 所以你可以在数据库中使用可空的DateTimetypes。 实体示例:

 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; } } 

在某些情况下, DateTime.MinValue (或等价地, default(DateTime) )用于指示未知的值。 这个简单的扩展方法可以帮助解决这个问题:

 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; } } 

用法:

  DateTime? dateToPassOnToDb = tooEarlyDate.ToNullIfTooEarlyForDb(); 

如果适合您的具体build模问题,可以将该字段设置为空。 空date不会被强制为不在SQL DateTime范围内的date键入默认值的方式。 另一个select是显式映射到一个不同的types,或许与,

 .HasColumnType("datetime2") 

我的解决scheme是将所有date时间列切换到datetime2,并使用datetime2任何新的列。 换句话说,使EF默认使用datetime2。 将其添加到您的上下文的OnModelCreating方法:

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

那会得到所有的DateTime和DateTime? 所有实体的属性。

尽pipe这个问题已经很老了,已经有了很好的答案,但我还是认为应该多解释一下这3个不同的方法来解决这个问题。

第一种方法

显式映射DateTime属性public virtual DateTime Start { get; set; } public virtual DateTime Start { get; set; } public virtual DateTime Start { get; set; }datetime2在表中相应的列中。 因为默认情况下EF会将其映射到datetime

这可以通过stream畅的API或数据注释来完成。

  1. stream利的API

    在DbContext类overide OnModelCreating和configuration属性Start (由于解释的原因,它是一个EntityClass类的属性)。

     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. 数据注释

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

第二种方法

在EntityClass构造函数中将Initialize初始化为一个默认值。这是很好的,因为如果由于某些原因,在将实体保存到数据库之前没有设置Start的值,start将始终有一个默认值。 确保默认值大于或等于SqlDateTime.MinValue (从1753年1月1日到9999年12月31日)

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

第三种方法

使Start是可以为空的DateTime -note ? DateTime之后 –

 public virtual DateTime? Start { get; set; } 

欲了解更多解释阅读这篇文章

如果你的DateTime属性在数据库中是可以空的,那么一定要使用DateTime? 对于关联的对象属性或EF将在DateTime.MinValue传递未分配的值,这些值在SQL datetimetypes可以处理的范围之外。

在构造函数中初始化Start属性

 Start = DateTime.Now; 

当我尝试使用Code First向ASP .Net Identity Framework的用户表(AspNetUsers)添加一些新字段时,这对我有用。 我更新了IdentityModels.cs中的Class – ApplicationUser,并添加了DateTimetypes的lastLogin字段。

 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; } } 

我有同样的问题,在我的情况下,我将date设置为新的DateTime()而不是DateTime.Now

在我的情况下,这发生在我使用实体时,sql表的默认值是datetime == getdate()。 所以我做了什么来设置这个领域的价值。

我使用数据库优先,当这个错误发生在我身上时,我的解决scheme是强制ProviderManifestToken =“2005”edmx文件(使模型与SQL Server 2005兼容)。 不知道Code First是否有类似的情况。