La conversion d'un type de données datetime2 en un type de données datetime a abouti à une valeur hors limites

174

J'ai le code suivant dans mon HomeController:

public ActionResult Edit(int id)
{
    var ArticleToEdit = (from m in _db.ArticleSet where m.storyId == id select m).First();
    return View(ArticleToEdit);
}

[ValidateInput(false)]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Article ArticleToEdit)
{
    var originalArticle = (from m in _db.ArticleSet where m.storyId == ArticleToEdit.storyId select m).First();
    if (!ModelState.IsValid)
        return View(originalArticle);

    _db.ApplyPropertyChanges(originalArticle.EntityKey.EntitySetName, ArticleToEdit);
    _db.SaveChanges();
    return RedirectToAction("Index");
}

Et voici la vue de la méthode Edit:

<% using (Html.BeginForm()) {%>

    <fieldset>
        <legend>Fields</legend>
        <p>
            <label for="headline">Headline</label>
            <%= Html.TextBox("headline") %>
        </p>
        <p>
            <label for="story">Story <span>( HTML Allowed )</span></label>
            <%= Html.TextArea("story") %>
        </p>
        <p>
            <label for="image">Image URL</label>
            <%= Html.TextBox("image") %>
        </p>
        <p>
            <input type="submit" value="Post" />
        </p>
    </fieldset>

<% } %>

Lorsque j'appuie sur le bouton Soumettre, j'obtiens l'erreur: {"The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.\r\nThe statement has been terminated."}Des idées sur le problème? Je suppose que la méthode d'édition essaie de mettre à jour la valeur publiée dans la base de données vers la version modifiée, mais pour une raison quelconque, elle ne l'aime pas ... Bien que je ne vois pas pourquoi la date est impliquée car elle n'est pas mentionnée dans le méthode de contrôleur pour modifier?

Cameron
la source
1
modelBuilder.Entity<WorldInfo>().Property(d => d.CurrentTime).HasColumnType("datetime2");
Anthony Nichols

Réponses:

166

Le problème est que vous utilisez ApplyPropertyChangesavec un objet de modèle qui n'a été rempli qu'avec des données dans le formulaire (titre, histoire et image). ApplyPropertyChangesapplique les modifications à toutes les propriétés de l'objet, y compris votre non initialisé DateTime, qui est défini sur 0001-01-01, qui est en dehors de la plage de SQL Server DATETIME.

Plutôt que d'utiliser ApplyPropertyChanges, je suggérerais de récupérer l'objet en cours de modification, de modifier les champs spécifiques que votre formulaire modifie, puis d'enregistrer l'objet avec ces modifications; de cette façon, seuls les champs modifiés sont modifiés. Alternativement, vous pouvez placer des entrées masquées dans votre page avec les autres champs renseignés, mais ce ne serait pas très convivial avec des modifications simultanées.

Mettre à jour:

Voici un exemple non testé de mise à jour de certains champs de votre objet (cela suppose que vous utilisez LINQ to SQL):

var story = _db.ArticleSet.First(a => a.storyId == ArticleToEdit.storyId);
story.headline = ArticleToEdit.headline;
story.story = ArticleToEdit.story;
story.image = ArticleToEdit.image;
story.modifiedDate = DateTime.Now;
_db.SubmitChanges();
Jacob
la source
Très utile :) Je me demandais pourquoi la date était modifiée alors que je ne l'avais pas spécifiée. Pouvez-vous aider à modifier la méthode Edit afin qu'elle n'utilise plus ApplyPropertyChanges? Comme je suis nouveau sur ASP.NET et que je ne comprends pas tout à fait pour le moment. Merci mon pote.
Cameron
Et si je voulais mettre la date à la date actuelle, c'est-à-dire. la date et l'heure à laquelle l'article a été mis à jour? Comme ce sera probablement la meilleure option et je suppose que cela fonctionnerait avec les ApplyPropertyChanges que j'ai en jeu.
Cameron
Voir ma modification (il suppose que modifiedDatec'est le nom de votre propriété)
Jacob
SubmitChanges ne fonctionne pas dans mon application: / est-il possible d'ajouter le story.modifiedDate = DateTime.Now;bit à mon code actuel? Merci
Cameron
1
cette erreur se produit lorsque nous définissons public DateTime CreatedDate au lieu de public DateTime? CreatedDate, car DateTime ne peut pas être null, alors pourquoi son erreur est hors de portée. cela peut être utile, mais cela a résolu mon problème.
adnan
115

Il s'agit d'une erreur courante que les gens rencontrent lors de l'utilisation d'Entity Framework. Cela se produit lorsque l'entité associée à la table en cours d'enregistrement a un champ datetime obligatoire et que vous ne le définissez pas avec une valeur.

L'objet datetime par défaut est créé avec une valeur de 01/01/1000et sera utilisé à la place de null. Cela sera envoyé à la colonne datetime qui peut contenir des valeurs de date de1753-01-01 00:00:00 partir de, mais pas avant, conduisant à l'exception hors plage.

Cette erreur peut être résolue en modifiant le champ de base de données pour accepter null ou en initialisant le champ avec une valeur.

Sanjay Kumar Madhva
la source
3
Cela se produit lorsque le champ datetime dans la base de données est facultatif et que la valeur n'est pas définie. Par conséquent, ce n'est pas une erreur courante des gens, c'est l'un des problèmes d'architecture EF.
GSoft Consulting
1
Je suis d'accord que EF devrait voir le type dans DB et ajuster en conséquence ou lancer ou au moins lancer une erreur plus précise. Sur le plan positif, j'aime votre réponse puisque vous avez fourni 2 options au lieu de l'habituelle - initialiser le fichier avec une valeur minimale.
DanteTheSmith
43

DATETIMEprend en charge 1753/1/1 à "l'éternité" (9999/12/31), tandis que le DATETIME2soutien 0001/1/1 à travers l'éternité.

Msdn

Réponse: Je suppose que vous essayez de sauvegarder DateTimeavec la valeur «0001/1/1». Il suffit de définir point d' arrêt et le déboguer, le cas échéant , puis remplacer DateTimeavec nulldate normale ou ensemble.

Andrew Orsich
la source
Mais que dois-je mettre dans le contrôleur? Le débogage soulève simplement l'erreur que j'ai publiée ci-dessus. Merci.
Cameron
semble erreur ici -> _db.SaveChanges (); Vous pouvez définir le point d'arrêt avant cette ligne ...
Andrew Orsich
Ouais, oui. Ensuite, il dit que c'est une erreur sur les SaveChanges, alors je regarde InnerException et il dit que c'est à cause de l'erreur publiée, c'est donc l'erreur!
Cameron
Avez-vous vérifié la valeur DateTime avant _db.SaveChanges (); a été appelé? Cela devrait être génial que «1753/1/1».
Andrew Orsich
La valeur de date de l'article d'origine est {18/10/2009 00:00:00} et la valeur de date de l'articleToEdit est {01/01/0001 00:00:00}, il semble donc que vous essayez de changer la date en 1er de tout ce qui n'est pas Je ne veux pas que je veux mais n'explique pas pourquoi il lance l'erreur car le format est le même, non?
Cameron
14

Celui-ci me rendait fou. Je voulais éviter d'utiliser une heure de date nullable ( DateTime?). Je n'avais pas non plus la possibilité d'utiliser le type datetime2 de SQL 2008 ( modelBuilder.Entity<MyEntity>().Property(e => e.MyDateColumn).HasColumnType("datetime2");).

J'ai finalement opté pour ce qui suit:

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

    private void UpdateDates()
    {
        foreach (var change in ChangeTracker.Entries<MyEntityBaseClass>())
        {
            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;
                    }
                }
            }
        }
    }
}
sky-dev
la source
10

Vous pouvez également résoudre ce problème en ajoutant au modèle (version Entity Framework> = 5)

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime CreationDate { get; set; }
Dongolo Jeno
la source
8

Si vous avez une colonne datetime et autorise null, vous obtiendrez cette erreur. Je recommande de définir une valeur à transmettre à l'objet avant .SaveChanges ();

Patrick
la source
5

J'ai eu cette erreur après avoir changé mon modèle (code d'abord) comme suit:

public DateTime? DateCreated

à

public DateTime DateCreated

Les lignes présentes avec une valeur nulle dans DateCreated ont provoqué cette erreur. J'ai donc dû utiliser l' instruction SQL UPDATE manuellement pour initialiser le champ avec une valeur standard.

Une autre solution pourrait être une spécification de la valeur par défaut du fichier.

Aleksandr Khomenko
la source
3

Dans mon cas, dans l'initialiseur de la classe que j'utilisais dans la table de la base de données, je ne définissais aucune valeur par défaut pour ma propriété DateTime, ce qui entraînait le problème expliqué dans la réponse de @Andrew Orsich. J'ai donc simplement rendu la propriété nullable. Ou j'aurais pu aussi lui donner DateTime.Now dans le constructeur. J'espère que ça aide quelqu'un.

StinkyCat
la source
3

Il semble que vous utilisez le framework d'entité. Ma solution était de basculer toutes les colonnes datetime sur datetime2 et d'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 sur votre contexte:

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

Cela obtiendra tous les DateTime et DateTime? properties sur toutes les entités de votre modèle.

Ogglas
la source
2

J'ai eu le même problème, malheureusement, j'ai deux propriétés DateTime sur mon modèle et une propriété DateTime est nulle avant de faire SaveChanges.

Assurez-vous donc que votre modèle a une valeur DateTime avant d'enregistrer les modifications ou rendez-le nullable pour éviter les erreurs:

public DateTime DateAdded { get; set; }   //This DateTime always has a value before persisting to the database.
public DateTime ReleaseDate { get; set; }  //I forgot that this property doesn't have to have DateTime, so it will trigger an error

Donc, cela résout mon problème, c'est une question de s'assurer que la date de votre modèle est correcte avant de persister dans la base de données:

public DateTime DateAdded { get; set; }
public DateTime? ReleaseDate { get; set; }
Willy David Jr
la source
2

Si vous utilisez la version Entity Framework> = 5, l'application de l'annotation [DatabaseGenerated (DatabaseGeneratedOption.Computed)] à vos propriétés DateTime de votre classe permettra au déclencheur de la table de base de données de faire son travail de saisie des dates de création d'enregistrement et de mise à jour d'enregistrement sans provoquer votre code Entity Framework pour bâillonner.

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime DateCreated { get; set; }

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime DateUpdated { get; set; }

Ceci est similaire à la 6ème réponse, écrite par Dongolo Jeno et éditée par Gille Q.

Jim Kay
la source
1

De plus, si vous ne connaissez pas une partie du code où l'erreur s'est produite, vous pouvez profiler une "mauvaise" exécution de sql en utilisant le profileur SQL intégré à mssql.

Un paramètre datetime incorrect affichera quelque chose comme ça:

mauvais paramètre

Nigrimmist
la source
1

Ce problème se produit généralement lorsque vous essayez de mettre à jour une entité. Par exemple, vous avez une entité qui contient un champ appelé DateCreatedqui est [Obligatoire] et lorsque vous insérez un enregistrement, aucune erreur n'est renvoyée mais lorsque vous souhaitez mettre à jour cette entité particulière, vous obtenez le

Erreur de conversion datetime2 hors plage.

Voici maintenant la solution:

Sur votre vue d'édition, c'est- edit.cshtmlà- dire pour les utilisateurs MVC, tout ce que vous avez à faire est d'ajouter un champ de formulaire caché pour votre DateCreatedjuste en dessous du champ caché pour la clé primaire des données d'édition.

Exemple:

@Html.HiddenFor(model => model.DateCreated)

En ajoutant ceci à votre vue d'édition, vous n'aurez jamais cette erreur, je vous assure.

Aduwu Joseph
la source
1

Vous devez activer la valeur nulle pour votre variable de date:

 public Nullable<DateTime> MyDate{ get; set; }
Badr Bellaj
la source
0

Essayez de rendre votre propriété nullable.

    public DateTime? Time{ get; set; }

A travaillé pour moi.

typhon04
la source
0

Si vous avez accès à la base de données, vous pouvez changer le type de colonne de la base de données de datetime à datetime2 (7) il enverra toujours un objet datetime et il sera enregistré

Sergiu Mindras
la source
0

Le modèle doit avoir une date / heure nullable. La méthode suggérée précédemment pour récupérer l'objet qui doit être modifié doit être utilisée à la place de ApplyPropertyChanges. Dans mon cas, j'avais cette méthode pour enregistrer mon objet:

public ActionResult Save(QCFeedbackViewModel item)

Et puis en service, je récupère en utilisant:

RETURNED = item.RETURNED.HasValue ? Convert.ToDateTime(item.RETURNED) : (DateTime?)null 

Le code de service complet est le suivant:

 var add = new QC_LOG_FEEDBACK()
            {

                QCLOG_ID = item.QCLOG_ID,
                PRE_QC_FEEDBACK = item.PRE_QC_FEEDBACK,
                RETURNED = item.RETURNED.HasValue ? Convert.ToDateTime(item.RETURNED) : (DateTime?)null,
                PRE_QC_RETURN = item.PRE_QC_RETURN.HasValue ? Convert.ToDateTime(item.PRE_QC_RETURN) : (DateTime?)null,
                FEEDBACK_APPROVED = item.FEEDBACK_APPROVED,
                QC_COMMENTS = item.QC_COMMENTS,
                FEEDBACK = item.FEEDBACK
            };

            _context.QC_LOG_FEEDBACK.Add(add);
            _context.SaveChanges();
anu
la source
0

[Résolu] Dans Entity Framework Code First (mon cas), il suffit de changer DateTimepour DateTime?résoudre mon problème.

/*from*/ public DateTime SubmitDate { get; set; }
/*to  */ public DateTime? SubmitDate { get; set; }
Amir Astaneh
la source
0

Erreur: la conversion d'un type de données datetime2 en type de données datetime a abouti à une valeur hors plage.

Cette erreur s'est produite en raison de NOT attribuer une valeur par rapport à une colonne de date NOT NULL dans l' utilisation de SQL DB EF et a été résolu en attribuant la même chose.

J'espère que cela t'aides!

user2964808
la source
0

Vous avez ce problème lors de la création de mes classes à partir de l'approche Database First. Résolu en utilisant simplement Convert.DateTime (dateCausingProblem) En fait, essayez toujours de convertir les valeurs avant de passer, cela vous évite des valeurs inattendues.

Ansar nisar Gill
la source
0

vous devez faire correspondre le format d'entrée de votre champ de date au format d'entité requis qui est aaaa / mm / jj

Marc
la source
1
Il y a d'autres réponses qui répondent à la question du PO, et elles ont été publiées il y a quelque temps. Lors de la publication d'une réponse, voir: Comment rédiger une bonne réponse? , assurez-vous d'ajouter une nouvelle solution ou une explication nettement meilleure, en particulier lorsque vous répondez à des questions plus anciennes.
help-info.de