【问题标题】:Using DateTime properties in Code-First Entity Framework and SQL Server在 Code-First Entity Framework 和 SQL Server 中使用 DateTime 属性
【发布时间】:2011-12-24 00:51:09
【问题描述】:

我有一个示例类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数据的转换 type 到 datetime 数据类型导致超出范围的值。这 语句已终止。


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

我在 .NET 4(MVC 3 Web 应用程序)和 SQL Server 2008 Express 上使用 EF4。

【问题讨论】:

  • 您是否将计算机的时钟设置为 1750 年或更早?
  • 我不是认真的 :) 看我的回答。

标签: datetime entity-framework-4 ef-code-first


【解决方案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);

...对于 DB 中的 datetime2(0) 列。

但是,您在问题中显示的代码有效,因为 datetime 类型允许将日期存储到 1750 年左右。该异常仅发生在较早的日期。此异常的一个常见原因是未初始化的 DateTime 属性,因为它表示不能存储在 SQL Server 的 datetime 列中的 0001 年。

没有相应的属性可以用数据注释来定义它。只有使用 Fluent API 才能实现。

【讨论】:

  • 我的代码示例中的DateAdded 属性是否已正确初始化?
  • @Paperjam:是的,但这完全是您测试过的代码,还是您的测试模型中可能还有另一个未初始化的DateTime 属性?如果不是,那是一件很奇怪的事情。我经常使用datetime 列,而DateTime 属性在使用Now 初始化时从来都不是问题。我昨天测试了你的例子再次说服自己,它没有抛出异常。
  • 噢!是的,我有一个未初始化的属性。我想我将从我的存储库模式模型开始,以避免像这样的愚蠢错误。谢谢您的帮助!我肯定会检查更多 Fluent API。
  • 注意 EF 版本 4.3.1 添加了一些修复。详情见此帖stackoverflow.com/questions/9466677/…
  • 注释确实有效!无需使用模型构建器
【解决方案2】:

保存日期时需要填充一个值。这就是您收到此错误的原因。

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

【讨论】:

  • 在我的示例代码中,当我初始化一个新的Book 类时,我将DateAdded 设置为DateTime.Now。值没有有效填充,还是我遗漏了什么?
  • 转念一想,确实如此。我记得我遇到的问题是我的存储库代码实际上没有设置DateAdded。并且使用可为空的字段,虽然对于防止我的疏忽引发错误很有用,但不会满足我的应用程序的要求。 +1 是一个很好的建议。
  • 如果你想要在你的模型中使用可空类型,但如果你不这样做,你不应该使用它,以便你的种子或其他初始化程序工作。
  • 如果我不想将其设为可为空,那么我的意思是项目要求不考虑该字段可为空。
【解决方案3】:

您可以使用 datetime2 类型注释您的类的属性。

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

【讨论】:

  • smalldatetime也可以使用
【解决方案4】:

如果启用了迁移,您还可以在此处进行调整。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-19
    • 1970-01-01
    • 1970-01-01
    • 2012-05-10
    • 2012-08-09
    • 2017-05-25
    • 1970-01-01
    • 2011-05-06
    相关资源
    最近更新 更多