2011-05-18 9 views
102

Estoy utilizando las API DbContext y Code First introducidas con Entity Framework 4.1.¿Cómo arreglar el error de conversión fuera de rango datetime2 usando DbContext y SetInitializer?

El modelo de datos utiliza tipos de datos básicos como string y DateTime. La única anotación de datos que estoy usando en algunos casos es [Required], pero eso no está en ninguna de las propiedades de DateTime. Ejemplo:

public virtual DateTime Start { get; set; } 

El DbContext subclase también es simple y se ve así:

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

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

El inicializador establece las fechas en el modelo de los valores sensibles en este año o el próximo año.

Sin embargo cuando funciono el inicializador, consigo este error en context.SaveChanges():

La conversión de un datos datetime2 tipo a un tipo de datos de fecha y hora dio como resultado en un valor fuera de rango. La declaración ha finalizado.

No entiendo por qué sucede esto, porque todo es muy simple. Tampoco estoy seguro de cómo solucionarlo ya que no hay ningún archivo edmx para editar.

¿Alguna idea?

+2

¿Puede utilizar el Analizador de SQL para ver insertar/actualizar sentencias de SQL? Es bastante difícil decir lo que está sucediendo aquí; no vemos su inicializador o entidades. SQL Profiler te ayudará mucho a localizar el problema. –

+1

En mi caso, agregué un campo a una tabla y modifiqué el formulario, olvidé actualizar Bind Includes y mi campo se estableció en NULL. Entonces el error ayudó a corregir mi descuido. – strattonn

Respuesta

160

Debe asegurarse de que Start sea mayor o igual a SqlDateTime.MinValue (1 de enero de 1753) - de manera predeterminada Start es igual a DateTime.MinValue (January 1, 0001).

+13

Había dejado algunos de mis objetos de inicialización sin una fecha establecida, por lo que habría estado predeterminado en DateTime.MinValue. –

+0

Lo hice también ^. Se agregó un campo de fecha personalizado al objeto ApplicationUser de identidad asp.net y luego se olvidó de inicializarlo en algo que tuviera sentido. : ( –

+0

En mi caso, el problema estaba en la fecha mínima, 01/01/0001 estaba generando el error. – Machado

12

Puede hacer que el campo sea nulo, si es que se ajusta a sus inquietudes específicas de modelado. No se forzará una fecha nula a una fecha que no esté dentro del rango del tipo SQL DateTime de la forma en que lo haría un valor predeterminado. Otra opción es mapear de forma explícita a un tipo diferente, tal vez con,

.HasColumnType("datetime2") 
18

En algunos casos, DateTime.MinValue (o equivalenly, default(DateTime)) se utiliza para indicar un valor desconocido. Este método simple extensión debe ayudar a manejar el problema:

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

Uso:

DateTime? dateToPassOnToDb = tooEarlyDate.ToNullIfTooEarlyForDb(); 
3

inicializar la propiedad de inicio en el constructor

Start = DateTime.Now; 

Esto funcionó para mí cuando yo estaba tratando de añadir pocos campos nuevos para la tabla de usuarios de .NET Identity Framework (AspNetUsers) utilizando Code First. Actualicé Class - ApplicationUser en IdentityModels.cs y agregué un campo lastLogin de tipo 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; } 
    } 
9

A pesar de que esta pregunta es bastante antiguo y hay grandes respuestas ya, pensé que debía poner uno más que explica 3 enfoques diferentes para resolver este problema.

primera aproximación

asignar explícitamente DateTime propiedad public virtual DateTime Start { get; set; } a datetime2 en la columna correspondiente en la tabla. Porque, por defecto, EF lo asignará al datetime.

Esto se puede hacer mediante una API fluida o una anotación de datos.

  1. API Fluido

    En DbContext overide clase OnModelCreating y configurar la propiedad Start (por razones de explicación que es una propiedad de la clase 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. anotación de datos

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

segundo enfoque

Inicializar Start a un valor predeterminado en entityClass constructor.This es bueno ya que si por alguna razón el valor de Start no se establece antes de guardar la entidad en el inicio de la base de datos siempre tendrá un valor predeterminado. Haga valor predeterminado seguro es mayor que o igual a SqlDateTime.MinValue (1 de enero de 1753 al 31 de diciembre de 9999)

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

tercera aproximación

Hacer Start a ser de tipo anulable DateTime-nota? después DateTime -

public virtual DateTime? Start { get; set; } 

Para una explicación más detallada de re anuncio de esta post

6

Si sus DateTime propiedades son anulable en la base de datos a continuación, asegúrese de utilizar DateTime? de las propiedades de los objetos asociados o EF pasará en DateTime.MinValue para los valores no asignados que se encuentra fuera del rango de lo que el tipo de fecha y hora de SQL puede manejar .

20

Simple. En su código primero, establezca el tipo de DateTime en DateTime ?. Para que pueda trabajar con el tipo de fecha y hora con nulos en la base de datos. Entidad ejemplo:

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

que no siempre es el caso. {1/1/0001 12:00: 00 AM} también hace que este error emerja –

0

En mi caso esto sucedió cuando utilicé entidad y la tabla de SQL tiene un valor por defecto de fecha y hora == getdate(). entonces qué hice para establecer un valor para este campo.

1

que tenían el mismo problema y en mi caso se establece la fecha como nueva DateTime() en lugar de DateTime.Now

8

Mi solución fue cambiar todas las columnas de fecha y hora a datetime2, y utilizar datetime2 de las nuevas columnas . En otras palabras, haga que EF use datetime2 por defecto.Esto, unido al método OnModelCreating en su contexto:

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

que hará que toda la fecha y hora y DateTime? propiedades en todas sus entidades.

0

Estoy utilizando Database First y cuando me pasó este error, mi solución fue forzar ProviderManifestToken = "2005" en el archivo edmx (haciendo que los modelos sean compatibles con SQL Server 2005). No sé si es posible algo similar para Code First.

Cuestiones relacionadas