A conversão de um tipo de dados datetime2 em um tipo de dados datetime resultou em um valor fora do intervalo

174

Eu tenho o seguinte código no meu 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");
}

E esta é a visão para o método 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>

<% } %>

Quando clico no botão Enviar, recebo o erro: {"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."}Alguma idéia de qual é o problema? Estou assumindo que o método de edição está tentando atualizar o valor postado no banco de dados para o editado, mas por algum motivo não está gostando ... Embora eu não veja por que a data está envolvida, pois não é mencionada no método de controlador para edição?

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

Respostas:

166

O problema é que você está usando ApplyPropertyChangesum objeto de modelo que só foi preenchido com dados no formulário (título, matéria e imagem). ApplyPropertyChangesaplica alterações a todas as propriedades do objeto, incluindo o não inicializado DateTime, definido como 0001-01-01, que está fora do intervalo do SQL ServerDATETIME .

Em vez de usar ApplyPropertyChanges , sugiro recuperar o objeto que está sendo modificado, alterar os campos específicos que seu formulário edita e salvar o objeto com essas modificações; Dessa forma, apenas os campos alterados são modificados. Como alternativa, você pode colocar entradas ocultas na sua página com os outros campos preenchidos, mas isso não seria muito amigável com as edições simultâneas.

Atualizar:

Aqui está um exemplo não testado de apenas atualizando alguns campos do seu objeto (assumindo que você esteja usando o 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
fonte
Muito útil :) Fiquei me perguntando por que a data estava sendo alterada quando não a havia especificado. Você pode ajudar a alterar o método Edit para que ele não use mais o ApplyPropertyChanges? Como sou novo no ASP.NET e não entendo tudo no momento. Valeu cara.
Cameron
E se eu quisesse definir a data para a data atual, ou seja. a data e hora em que o artigo foi atualizado? Como essa provavelmente será a melhor opção, presumo que funcionaria com as ApplyPropertyChanges que tenho em jogo.
Cameron
Veja minha edição (ele assume que modifiedDateé o nome de sua propriedade)
Jacob
SubmitChanges não funciona no meu aplicativo: / é possível adicionar o story.modifiedDate = DateTime.Now;bit ao meu código atual? Graças
Cameron
1
esse erro ocorre quando definimos public DateTime CreatedDate em vez de public DateTime? CreatedDate, porque DateTime não pode ser nulo; por isso, é um erro fora do intervalo. pode ser útil, mas resolveu o meu problema.
adnan 23/05
115

Esse é um erro comum que as pessoas enfrentam ao usar o Entity Framework. Isso ocorre quando a entidade associada à tabela que está sendo salva possui um campo de data e hora obrigatório e você não a define com algum valor.

O objeto de data e hora padrão é criado com um valor de 01/01/1000e será usado no lugar de null. Isso será enviado para a coluna datetime, que pode conter valores de data de1753-01-01 00:00:00 diante, mas não antes, levando à exceção fora do intervalo.

Este erro pode ser resolvido modificando o campo do banco de dados para aceitar nulo ou inicializando o campo com um valor.

Sanjay Kumar Madhva
fonte
3
Isso acontece quando o campo datetime no banco de dados é opcional e o valor não está definido. Portanto, isso não é erro de pessoas comuns, esse é um dos problemas de arquitetura da EF.
GSoft Consulting
1
Concordo que a EF deve ver o tipo no DB e ajustar de acordo ou lançar ou, pelo menos, lançar um erro mais preciso. No lado positivo, gosto da sua resposta, já que você forneceu duas opções em vez da usual - inicialize o arquivo com o valor mínimo.
DanteTheSmith
43

DATETIMEsuporta 1753/1/1 para "eternidade" (9999/12/31), enquanto DATETIME2suporta 0001/1/1 por toda a eternidade.

Msdn

Resposta: Suponho que você tente salvar DateTimecom o valor '0001/1/1'. Basta definir o ponto de interrupção e depurá-lo; se houver, substitua DateTimepor nullou defina a data normal.

Andrew Orsich
fonte
O que eu coloco no Controller? A depuração apenas traz esse erro que eu publiquei acima. Obrigado.
Cameron
parece erro aqui -> _db.SaveChanges (); É possível definir ponto de interrupção antes desta linha ...
Andrew Orsich
Sim fez. Então ele diz que é um erro no SaveChanges, então eu olho para o InnerException e diz que é por causa do erro postado, então esse é o erro!
Cameron
Você verificou o valor DateTime antes de _db.SaveChanges (); foi chamado? Deve ser ótimo que '1753/1/1'.
Andrew Orsich 5/11/11
O valor da data originalArticle é {18/10/2009 00:00:00} e o valor da data ArticleToEdit é {01/01/0001 00:00:00}, portanto parece que está tentando alterar a data para 1º de tudo o que não é quero que eu quero, mas não explica por que está lançando o erro, pois o formato é o mesmo, certo?
Cameron
14

Este estava me deixando louco. Eu queria evitar o uso de uma data e hora anulável ( DateTime?). Também não tive a opção de usar o tipo datetime2 do SQL 2008 ( modelBuilder.Entity<MyEntity>().Property(e => e.MyDateColumn).HasColumnType("datetime2");).

Acabei optando pelo seguinte:

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
fonte
10

Você também pode corrigir esse problema adicionando ao modelo (versão do Entity Framework> = 5)

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

Se você possui uma coluna datetime e permite null, você receberá esse erro. Eu recomendo definir um valor para passar para o objeto antes de .SaveChanges ();

Patrick
fonte
5

Eu recebi esse erro depois de alterar meu modelo (primeiro o código) da seguinte maneira:

public DateTime? DateCreated

para

public DateTime DateCreated

As linhas presentes com valor nulo em DateCreated causaram esse erro. Então, eu tive que usar a instrução SQL UPDATE manualmente para inicializar o campo com um valor padrão.

Outra solução poderia ser uma especificação do valor padrão para o arquivado.

Aleksandr Khomenko
fonte
3

No meu caso, no inicializador da classe que eu estava usando na tabela do banco de dados, não estava definindo nenhum valor padrão para minha propriedade DateTime, resultando no problema explicado na resposta de @Andrew Orsich. Então, acabei de tornar a propriedade anulável. Ou eu também poderia ter dado o DateTime.Now no construtor. Espero que ajude alguém.

StinkyCat
fonte
3

Parece que você está usando uma estrutura de entidade. Minha solução foi alternar todas as colunas datetime para datetime2 e usar datetime2 para novas colunas; em outras palavras, fazer com que o EF use datetime2 por padrão. Adicione isso ao método OnModelCreating no seu contexto:

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

Isso receberá todos os DateTime e DateTime? propriedades em todas as entidades em seu modelo.

Ogglas
fonte
2

Eu tive o mesmo problema, infelizmente, tenho duas propriedades DateTime no meu modelo e uma propriedade DateTime é nula antes de salvar SaveChanges.

Portanto, verifique se o modelo possui o valor DateTime antes de salvar as alterações ou anulá-lo para evitar erros:

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

Portanto, isso resolve meu problema, é uma questão de garantir que a data do modelo esteja correta antes de persistir no banco de dados:

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

Se você estiver usando o Entity Framework versão> = 5, aplicando a anotação [DatabaseGenerated (DatabaseGeneratedOption.Computed)] às propriedades DateTime da sua classe permitirá que o gatilho da tabela do banco de dados faça seu trabalho de inserir datas para criação e atualização de registros sem causar seu código do Entity Framework para amordaçar.

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

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

É semelhante à 6ª resposta, escrita por Dongolo Jeno e editada por Gille Q.

Jim Kay
fonte
1

Além disso, se você não conhece parte do código onde ocorreu o erro, pode criar um perfil de execução "ruim" do sql usando o sql profiler integrado ao mssql.

O parâmetro datetime incorreto exibirá algo assim:

param ruim

Nigrimmist
fonte
1

Esse problema geralmente ocorre quando você está tentando atualizar uma entidade. Por exemplo, você tem uma entidade que contém um campo chamado DateCreatedque é [Obrigatório] e quando você inserção de registro, nenhum erro será retornado, mas quando você deseja atualizar essa entidade particular, você a obter o

erro de conversão fora do intervalo datetime2.

Agora, aqui está a solução:

Na sua visualização de edição, ou seja, edit.cshtmlpara usuários do MVC, tudo o que você precisa fazer é adicionar um campo de formulário oculto para o seuDateCreated logo abaixo do campo oculto, para a chave primária dos dados de edição.

Exemplo:

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

Adicionando isso à sua visualização de edição, você nunca terá esse erro, garanto.

Aduwu Joseph
fonte
1

Você precisa habilitar o valor nulo para sua variável de data:

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

Tente tornar sua propriedade anulável.

    public DateTime? Time{ get; set; }

Trabalhou para mim.

typhon04
fonte
0

Se você tiver acesso ao banco de dados, poderá alterar o tipo de coluna do banco de dados para datetime para datetime2 (7). Ele ainda enviará um objeto datetime e será salvo.

Sergiu Mindras
fonte
0

O modelo deve ter data / hora anulável. O método sugerido anteriormente para recuperar o objeto que precisa ser modificado deve ser usado em vez de ApplyPropertyChanges. No meu caso, eu tinha esse método para salvar meu objeto:

public ActionResult Save(QCFeedbackViewModel item)

E, em serviço, recupero usando:

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

O código de serviço completo é o seguinte:

 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
fonte
0

[Resolvido] No Entity Framework Code Primeiro (meu caso) apenas mudando DateTimepara DateTime?resolver o meu problema.

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

Erro: a conversão de um tipo de dados datetime2 para um tipo de dados datetime resultou em um valor fora do intervalo.

Este erro ocorreu quando devido a NÃO atribuir qualquer valor a uma coluna de data NOT NULL no SQL DB usando EF e foi resolvido atribuindo o mesmo.

Espero que isto ajude!

user2964808
fonte
0

Tenho esse problema quando criei minhas classes da abordagem Database First. Resolvido usando simplesmente Convert.DateTime (dateCausingProblem) Na verdade, sempre tente converter valores antes de passar, ele evita valores inesperados.

Ansar nisar Gill
fonte
0

você deve corresponder o formato de entrada do seu campo de data ao formato de entidade necessário, que é aaaa / mm / dd

marc
fonte
1
Existem outras respostas que fornecem a pergunta do OP e foram publicadas há algum tempo. Ao postar uma resposta, consulte: Como redigir uma boa resposta? , adicione uma nova solução ou uma explicação substancialmente melhor, especialmente ao responder a perguntas mais antigas.
Help -info.de 27/10/19