Подтвердить что ты не робот

Использование свойств DateTime в Code-First Entity Framework и SQL Server

У меня есть пример класса book:

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

Когда я пытаюсь добавить новый book в контекст BookDb...

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

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

... выдается ошибка:

System.Data.SqlClient.SqlException: преобразование данных datetime2 тип к типу данных даты и времени привел к превышению значения. утверждение завершено.


Я обнаружил, что причиной этого являются несовместимые типы datetime между .NET и SQL Server. Есть способ сказать EF использовать формат SQL Server в традиционной Entity Framework, но как это сделать в Code-First Entity Framework?

Я использую EF4 для .NET 4 (веб-приложение MVC 3) и SQL Server 2008 Express.

4b9b3361

Ответ 1

Вы можете указать тип в Fluent API:

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

Это создает столбец datetime2(7) в базе данных. Если вы хотите уточнить точность, которую вы можете использовать:

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

... для столбца datetime2(0) в БД.

Однако код, который вы указали в своем вопросе, работает, потому что тип datetime позволяет хранить даты примерно до 1750. Исключение происходит только для более ранних дат. Общей причиной этого исключения является неинициализированное свойство datetime, поскольку оно представляет год 0001, который не может быть сохранен в столбце datetime на SQL Server.

Нет соответствующего атрибута для определения этого с аннотациями данных. Это возможно только с Fluent API.

Ответ 2

При сохранении даты необходимо, чтобы значение было заполнено. Вот почему вы получаете эту ошибку.

Просто используйте DateTime?. Нет необходимости в волшебстве выше.

Ответ 3

Вы можете аннотировать атрибут вашего класса с типом datetime2.

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

Ответ 4

Если миграция включена, вы также можете настроить материал прямо там.

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