在代码优先实体框架和SQL Server中使用DateTime属性

在代码优先实体框架和SQL Server中使用DateTime属性,datetime,entity-framework-4,ef-code-first,Datetime,Entity Framework 4,Ef Code First,我有一本示例类书: public class Book { [Key] public int Id { get; set; } public string Name { get; set; } public DateTime DateAdded { get; set; } } 当我尝试向BookDb上下文添加新的book时 using (BookDb db = new BookDb()) { Book book = new Book {

我有一本示例类

public class Book
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime DateAdded { get; set; }
}
当我尝试向
BookDb
上下文添加新的
book

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数据的转换 类型转换为日期时间数据类型导致值超出范围。这个 声明已终止


我发现造成这种情况的原因是.NET和SQL Server之间不兼容的
datetime
类型。有一种方法可以告诉EF在传统实体框架中使用SQL Server的格式,但是如何在代码优先实体框架中使用它?


我正在使用.NET 4(MVC 3 web app)上的EF4和SQL Server 2008 Express。

您可以在Fluent API中指定类型:

modelBuilder.Entity<Book>()
    .Property(f => f.DateTimeAdded)
    .HasColumnType("datetime2");
。。。对于数据库中的
datetime2(0)

但是,问题中显示的代码是有效的,因为
datetime
类型允许存储1750年左右的日期。只有较早的日期才会出现例外情况。此异常的常见原因是未初始化的
DateTime
属性,因为它表示无法存储在SQL Server中的
DateTime
列中的0001年


没有相应的属性可以使用数据注释定义此属性。只有使用Fluent API时才可能。保存日期时,需要填充值。这就是为什么会出现这个错误


只需使用
DateTime?
。不需要上面的魔法。

您可以使用datetime2类型为类的属性添加注释

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

如果启用了迁移,您还可以在那里调整内容

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

您是否将计算机的时钟设置为1750年或更早?我不是认真的:)请参见我的答案。在我的代码示例中,
DateAdded
属性是否正确初始化?@Paperjam:It,但是,这是否正是您测试过的代码,或者您的测试模型中是否存在另一个未初始化的
DateTime
属性?如果不是,那就是一件奇怪的事情。我经常使用
datetime
列,当使用
Now
初始化时,
datetime
属性从来都不是问题。我昨天测试了你的例子,再次说服我自己,它没有抛出一个异常。啊!是的,我有一个未初始化的属性。我想我将从我的存储库模式模型开始,以避免像这样愚蠢的错误。谢谢你的帮助!我肯定会查看更多的Fluent API。注意EF版本4.3.1添加了一些修复。请参阅本文了解注释的详细信息!在我的示例代码中不需要使用ModelBuilder,当我初始化一本新的
类时,我将
DateAdd
设置为
DateTime.Now
。是不是有效地填充了值,还是我遗漏了什么?再想想,是的。我记得我遇到的问题是,我的存储库代码实际上没有设置
DateAdded
。使用可为空的字段虽然有助于防止我的疏忽引发错误,但不符合我的应用程序的要求+1,一个好的建议。如果你想在你的模型中使用一个可空类型,但是如果你不使用它,你就不应该只使用种子或其他初始化器。如果我不想使它无效,就意味着该项目不考虑这个字段nulable。SimultDeaTimes也可以使用。
public override void Up()
{
    CreateTable(
        "dbo.MyTable",
        c => new
        {
            Date = c.DateTime(false, 7, storeType: "datetime2"),
        });
}