在代码优先实体框架和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"),
});
}