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 ?

8voto

Christopher King Points 576

Si votre DateTime sont nullables dans la base de données, assurez-vous d'utiliser les propriétés DateTime? pour les propriétés de l'objet associé ou EF passera en DateTime.MinValue pour les valeurs non assignées, ce qui est en dehors de la plage de ce que le type datetime de SQL peut gérer.

8voto

Ogglas Points 1

Ma solution a consisté à remplacer toutes les colonnes datetime par datetime2, et à utiliser datetime2 pour toutes les nouvelles colonnes. En d'autres termes, faire en sorte que EF utilise datetime2 par défaut. Ajoutez ceci à la méthode OnModelCreating de votre contexte :

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

Vous obtiendrez ainsi toutes les propriétés DateTime et DateTime ? de toutes vos entités.

3voto

jdwolf Points 1026

Initialiser la propriété Start dans le constructeur

Start = DateTime.Now;

Cela a fonctionné pour moi lorsque j'ai essayé d'ajouter quelques nouveaux champs à la table Users (AspNetUsers) du cadre d'identité ASP .Net en utilisant Code First. J'ai mis à jour la classe ApplicationUser dans IdentityModels.cs et j'ai ajouté un champ lastLogin de 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; }
    }

3voto

Hamza Khanzada Points 1102

D'après la réponse de l'utilisateur @andygjp, il est préférable de remplacer la base Db.SaveChanges() et ajoutez une fonction pour remplacer toute date qui n'est pas comprise entre SqlDateTime.MinValue et SqlDateTime.MaxValue.

Voici un exemple de 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;
                    }
                }
            }
        }
    }
}

Tiré du commentaire de l'utilisateur @sky-dev sur https://stackoverflow.com/a/11297294/9158120

1voto

sam Points 702

J'ai eu le même problème et dans mon cas, j'ai défini la date avec new DateTime() au lieu de DateTime.Now.

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