Estou usando as APIs DbContext e Code First introduzidas no Entity Framework 4.1.
O modelo de dados usa tipos de dados básicos, como string
e DateTime
. A única anotação de dados que estou usando em alguns casos é [Required]
, mas isso não está em nenhuma das DateTime
propriedades. Exemplo:
public virtual DateTime Start { get; set; }
A subclasse DbContext também é simples e se parece com:
public class EventsContext : DbContext
{
public DbSet<Event> Events { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Event>().ToTable("Events");
}
}
O inicializador define datas no modelo para valores sensíveis neste ano ou no próximo ano.
No entanto, quando executo o inicializador, recebo este erro em context.SaveChanges()
:
A conversão de um tipo de dados datetime2 para um tipo de dados datetime resultou em um valor fora do intervalo. A instrução foi encerrada.
Não entendo por que isso está acontecendo, porque tudo é muito simples. Também não tenho certeza de como corrigi-lo, pois não há arquivo edmx para editar.
Alguma ideia?
fonte
Respostas:
Você deve garantir que Start seja maior ou igual a SqlDateTime.MinValue (1 de janeiro de 1753) - por padrão, Start é igual a DateTime.MinValue (1 de janeiro de 0001).
fonte
Simples. No seu código primeiro, defina o tipo de DateTime como DateTime? Então você pode trabalhar com o tipo DateTime anulável no banco de dados. Exemplo de entidade:
fonte
Em alguns casos,
DateTime.MinValue
(ou equivalentedefault(DateTime)
) , é usado para indicar um valor desconhecido.Este método de extensão simples pode ajudar a lidar com essas situações:
Uso:
fonte
Você pode tornar o campo anulável, se isso atender às suas preocupações específicas de modelagem. Uma data nula não será coagida para uma data que não esteja dentro do intervalo do tipo SQL DateTime da mesma forma que um valor padrão. Outra opção é mapear explicitamente para um tipo diferente, talvez com,
fonte
Embora essa pergunta seja bastante antiga e já haja ótimas respostas, pensei em colocar mais uma que explique três abordagens diferentes para resolver esse problema.
1ª Abordagem
Mapeie explicitamente a
DateTime
propriedadepublic virtual DateTime Start { get; set; }
paradatetime2
na coluna correspondente da tabela. Porque, por padrão, a EF fará o mapeamento paradatetime
.Isso pode ser feito por API fluente ou anotação de dados.
API fluente
Na classe DbContext, substitua
OnModelCreating
e configure a propriedadeStart
(por motivos de explicação, é uma propriedade da classe EntityClass).Anotação de dados
2ª Abordagem
Inicialize
Start
com um valor padrão no construtor EntityClass. Isso é bom como se, por algum motivo, o valor deStart
não estivesse definido antes de salvar a entidade no início do banco de dados sempre terá um valor padrão. Verifique se o valor padrão é maior ou igual a SqlDateTime.MinValue (de 1 de janeiro de 1753 a 31 de dezembro de 9999)3ª Abordagem
Tornar
Start
para ser do tipo anulávelDateTime
-note?
apósDateTime
-Para mais explicações leia este post
fonte
Se suas
DateTime
propriedades forem anuláveis no banco de dados, certifique-se de usarDateTime?
as propriedades do objeto associado ou o EF passaráDateTime.MinValue
por valores não atribuídos que estão fora do intervalo com o qual o tipo de data e hora do SQL pode manipular.fonte
Minha solução foi alternar todas as colunas datetime para datetime2 e usar datetime2 para novas colunas. Em outras palavras, faça com que o EF use datetime2 por padrão. Adicione isso ao método OnModelCreating no seu contexto:
Isso receberá todos os DateTime e DateTime? propriedades em todas as suas entidades.
fonte
inicialize a propriedade Start no construtor
Isso funcionou para mim quando eu estava tentando adicionar alguns novos campos à tabela Usuários do ASP .Net Identity Framework (AspNetUsers) usando o Code First. Atualizei o Class - ApplicationUser no IdentityModels.cs e adicionei um campo lastLogin do tipo DateTime.
fonte
Com base na resposta do usuário @ andygjp, é melhor substituir o
Db.SaveChanges()
método base e adicionar uma função para substituir qualquer data que não esteja entre SqlDateTime.MinValue e SqlDateTime.MaxValue.Aqui está o código de exemplo
Retirado do comentário do usuário @ sky-dev em https://stackoverflow.com/a/11297294/9158120
fonte
Eu tive o mesmo problema e, no meu caso, estava definindo a data como novo DateTime () em vez de DateTime.Now
fonte
No meu caso, isso aconteceu quando usei a entidade e a tabela sql tem o valor padrão de datetime == getdate (). Então, o que eu fiz para definir um valor para este campo.
fonte
Estou usando o Database First e, quando esse erro ocorreu, minha solução foi forçar o ProviderManifestToken = "2005" no arquivo edmx (tornando os modelos compatíveis com o SQL Server 2005). Não sei se algo semelhante é possível para o Code First.
fonte
Uma linha corrige isso:
Então, no meu código, adicionei:
Adicionar essa linha à seção de substituição da subclasse DBContext void OnModelCreating deve funcionar.
fonte
No meu caso, após algumas refatorações no EF6, meus testes falharam com a mesma mensagem de erro do pôster original, mas minha solução não teve nada a ver com os campos DateTime.
Estava faltando um campo obrigatório ao criar a entidade. Depois de adicionar o campo ausente, o erro desapareceu. Minha entidade tem dois DateTime? campos, mas eles não eram o problema.
fonte