web-dev-qa-db-fra.com

Utilisation des propriétés DateTime dans Code-First Entity Framework et SQL Server

J'ai un exemple de classe book:

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

Lorsque j'essaie d'ajouter un nouveau book au contexte BookDb ...

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

    db.Books.Add(book);
    db.SaveChanges();
}

... une erreur est levée:

System.Data.SqlClient.SqlException: La conversion d'un type de données datetime2 en un type de données datetime a entraîné une valeur hors plage. La déclaration est terminée.


J'ai trouvé que la cause de ceci était les types datetime incompatibles entre .NET et SQL Server. Il existe un moyen de dire à EF d'utiliser le format de SQL Server dans Entity Framework traditionnel, mais comment le faire dans Code-First Entity Framework?

J'utilise EF4 sur .NET 4 (application Web MVC 3) et SQL Server 2008 Express.

27
Chad Levy

Vous pouvez spécifier le type dans Fluent API:

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

Cela crée une colonne datetime2(7) dans la base de données. Si vous souhaitez affiner la précision que vous pouvez utiliser:

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

... pour une colonne datetime2(0) dans la base de données.

Cependant, le code que vous avez montré dans votre question fonctionne car le type datetime permet de stocker des dates vers 1750. L'exception se produit uniquement pour les dates antérieures. Une raison courante de cette exception est une propriété DateTime non initialisée car elle représente l'année 0001 qui ne peut pas être stockée dans une colonne datetime dans SQL Server.

Il n'y a pas d'attribut correspondant pour définir cela avec des annotations de données. Cela n'est possible qu'avec l'API Fluent.

48
Slauma

Lors de la sauvegarde d'une date, une valeur doit être renseignée. C'est pourquoi vous obtenez cette erreur.

Utilisez simplement DateTime?. Il n'y a pas besoin de la magie ci-dessus.

30
Houman

Vous pouvez annoter l'attribut de votre classe avec le type datetime2.

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

Si les migrations sont activées, vous pouvez également ajuster les éléments directement sur place.

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