datetime - foreign - data annotations entity framework
Utilizar las propiedades de DateTime en Code-First Entity Framework y SQL Server (4)
Tengo un book
clase de ejemplo:
public class Book
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public DateTime DateAdded { get; set; }
}
Cuando intento agregar un nuevo book
al contexto de BookDb
...
using (BookDb db = new BookDb())
{
Book book = new Book {
Name = "Some name",
DateAdded = DateTime.Now
};
db.Books.Add(book);
db.SaveChanges();
}
... se produce un error:
System.Data.SqlClient.SqlException : la conversión de un tipo de datos datetime2 a un tipo de datos datetime resultó en un valor fuera de rango. La instrucción se ha terminado.
Descubrí que la causa de esto son los tipos de datetime
y datetime
incompatibles entre .NET y SQL Server. Hay una forma de decirle a EF que use el formato de SQL Server en Entity Framework tradicional, pero ¿cómo lo hago en Code-First Entity Framework?
Estoy usando EF4 en .NET 4 (aplicación web MVC 3) y SQL Server 2008 Express.
Al guardar una fecha, debe tener un valor poblado. Es por eso que obtienes este error.
Solo usa DateTime?
. No hay necesidad de la magia de arriba.
Puede anotar el atributo de su clase con el tipo datetime2.
public class Book
{
[Column(TypeName = "datetime2")]
public DateTime DateAdded { get; set; }
}
Puede especificar el tipo en la API Fluent:
modelBuilder.Entity<Book>()
.Property(f => f.DateTimeAdded)
.HasColumnType("datetime2");
Esto crea una columna datetime2(7)
en la base de datos. Si quieres afinar la precisión, puedes usar:
modelBuilder.Entity<Book>()
.Property(f => f.DateTimeAdded)
.HasColumnType("datetime2")
.HasPrecision(0);
... para una columna datetime2(0)
en el DB.
Sin embargo, el código que ha mostrado en su pregunta funciona porque el tipo de datetime
permite almacenar fechas de alrededor de 1750. La excepción se produce solo en fechas anteriores. Una razón común para esta excepción es una propiedad DateTime
no inicializada porque representa el año 0001 que no se puede almacenar en una columna de datetime
y datetime
en SQL Server.
No hay un atributo correspondiente para definir esto con anotaciones de datos. Solo es posible con Fluent API.
Si las migraciones están habilitadas, también puedes ajustar cosas allí mismo.
public override void Up()
{
CreateTable(
"dbo.MyTable",
c => new
{
Date = c.DateTime(false, 7, storeType: "datetime2"),
});
}