Utilizzo delle proprietà DateTime in Code-First Entity Framework e SQL Server

Ho un book class di esempio:

 public class Book { [Key] public int Id { get; set; } public string Name { get; set; } public DateTime DateAdded { get; set; } } 

Quando tento di aggiungere un nuovo book al contesto di BookDb

 using (BookDb db = new BookDb()) { Book book = new Book { Name = "Some name", DateAdded = DateTime.Now }; db.Books.Add(book); db.SaveChanges(); } 

… viene generato un errore:

System.Data.SqlClient.SqlException : la conversione di un tipo di dati datetime2 in un tipo di dati datetime ha comportato un valore fuori intervallo. La dichiarazione è stata chiusa.


Ho scoperto che la causa di questo è i tipi datetime incompatibili tra .NET e SQL Server. C’è un modo per dire a EF di usare il formato di SQL Server nel tradizionale Entity Framework, ma come faccio a farlo in Code-First Entity Framework?

Utilizzo EF4 su .NET 4 (app Web MVC 3) e SQL Server 2008 Express.

Puoi specificare il tipo in Fluent API:

 modelBuilder.Entity() .Property(f => f.DateTimeAdded) .HasColumnType("datetime2"); 

Questo crea una colonna datetime2(7) nel database. Se si desidera ottimizzare la precisione, è ansible utilizzare:

 modelBuilder.Entity() .Property(f => f.DateTimeAdded) .HasColumnType("datetime2") .HasPrecision(0); 

… per una colonna datetime2(0) nel DB.

Tuttavia, il codice che hai mostrato nella tua domanda funziona perché il tipo datetime consente di memorizzare le date intorno al 1750. L’eccezione si verifica solo per date precedenti. Un motivo comune per questa eccezione è una proprietà DateTime non inizializzata poiché rappresenta l’anno 0001 che non può essere archiviato in una colonna datetime in SQL Server.

Non esiste un attributo corrispondente per definire questo con annotazioni di dati. È ansible solo con l’API Fluent.

Quando si salva una data, è necessario che venga popolato un valore. Ecco perché si ottiene questo errore.

Basta usare DateTime? . Non è necessario per la magia di cui sopra.

È ansible annotare l’attributo della class con il tipo datetime2.

 public class Book { [Column(TypeName = "datetime2")] public DateTime DateAdded { get; set; } } 

Se le migrazioni sono abilitate puoi anche aggiustare le cose proprio lì.

 public override void Up() { CreateTable( "dbo.MyTable", c => new { Date = c.DateTime(false, 7, storeType: "datetime2"), }); }