140 votes

Comment corriger l'erreur de conversion datetime2 out-of-range en utilisant DbContext et SetInitializer ?

J'utilise les API DbContext et Code First introduites avec Entity Framework 4.1.

Les modèle de données utilise des types de données de base tels que string y DateTime . La seule annotation de données que j'utilise dans certains cas est [Required] mais cela ne figure sur aucun des sites de l DateTime propriétés. Exemple :

public virtual DateTime Start { get; set; }

Les Sous-classe de DbContext est également simple et se présente comme suit :

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

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

Les initialisateur fixe des dates dans le modèle à des valeurs raisonnables de cette année ou de l'année prochaine.

Cependant, lorsque j'exécute l'initialisateur, j'obtiens l'erreur suivante context.SaveChanges() :

La conversion de en un type de données da une valeur hors plage. [ ] a été interrompue.

Je ne comprends pas du tout pourquoi cela se produit, car tout est si simple. Je ne sais pas non plus comment résoudre ce problème puisqu'il n'y a pas de fichier edmx à éditer.

Des idées ?

196voto

andygjp Points 588

Vous devez vous assurer que le début est supérieur ou égal à SqlDateTime.MinValue (1er janvier 1753) - par défaut, le début est égal à DateTime.MinValue (1er janvier 0001).

24voto

Ulisses Ottoni Points 341

Simple. Dans votre code, définissez d'abord le type de DateTime à DateTime ? Ainsi, vous pouvez travailler avec le type DateTime nullable dans la base de données. Exemple d'entité :

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

23voto

Kjartan Points 5805

Dans certains cas, DateTime.MinValue (ou de manière équivalente, default(DateTime) ) est utilisé pour indiquer une valeur inconnue.

Cette méthode d'extension simple peut aider à gérer de telles 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;
    }
}

Utilisation :

 DateTime? dateToPassOnToDb = tooEarlyDate.ToNullIfTooEarlyForDb();

13voto

Brian Kretzler Points 6012

Vous pouvez rendre le champ nullable, si cela correspond à vos préoccupations en matière de modélisation. Une date nulle ne sera pas contrainte à une date qui n'est pas dans l'intervalle du type DateTime de SQL, comme le serait une valeur par défaut. Une autre option est de mapper explicitement vers un type différent, par exemple avec ,

.HasColumnType("datetime2")

13voto

AIM Points 882

Bien que cette question soit assez ancienne et qu'il y ait déjà d'excellentes réponses, j'ai pensé qu'il fallait en ajouter une autre qui explique trois approches différentes pour résoudre ce problème.

1ère approche

Tracer explicitement la carte DateTime propriété public virtual DateTime Start { get; set; } a datetime2 dans la colonne correspondante du tableau. Parce que, par défaut, EF l'affecte à datetime .

Cela peut se faire par le biais d'une API fluide ou d'une annotation de données.

  1. API fluide

    Dans la classe DbContext, remplacer OnModelCreating et configurer les propriétés Start (pour des raisons d'explication, il s'agit d'une propriété de la classe 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. Annotation des données

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

2ème approche

Initialiser Start à une valeur par défaut dans le constructeur d'EntityClass, car si pour une raison ou une autre la valeur de Start n'est pas défini avant l'enregistrement de l'entité dans la base de données, start aura toujours une valeur par défaut. Assurez-vous que la valeur par défaut est supérieure ou égale à SqlDateTime.MinValue ( du 1er janvier 1753 au 31 décembre 9999)

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

3ème approche

Faire Start pour être de type nullable DateTime -Note ? après DateTime -

public virtual DateTime? Start { get; set; }

Pour plus d'explications, lisez ceci poste

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X