Использование свойств 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.
Ответы
Ответ 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"),
});
}