Ale*_*gas 132 .net c# entity-framework ef-code-first dbcontext
我正在使用Entity Framework 4.1中引入的DbContext和Code First API.
该数据模型使用的基本数据类型,如string和DateTime.我在某些情况下使用的唯一数据注释是[Required],但这不是任何DateTime属性.例:
public virtual DateTime Start { get; set; }
Run Code Online (Sandbox Code Playgroud)
该的DbContext子类也很简单,看起来像:
public class EventsContext : DbContext
{
public DbSet<Event> Events { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Event>().ToTable("Events");
}
}
Run Code Online (Sandbox Code Playgroud)
在初始化设置日期在模型中有意义的值在今年或明年.
但是,当我运行初始化程序时,我收到此错误context.SaveChanges():
将datetime2数据类型转换为日期时间数据类型会导致超出范围的值.该语句已终止.
我不明白为什么会发生这种情况,因为一切都很简单.我也不确定如何解决它,因为没有edmx文件可以编辑.
有任何想法吗?
小智 183
您必须确保Start大于或等于SqlDateTime.MinValue(1753年1月1日) - 默认情况下,Start等于DateTime.MinValue(0001年1月1日).
小智 22
简单.首先在代码中,将DateTime的类型设置为DateTime?.因此,您可以在数据库中使用可空的DateTime类型.实体示例:
public class Alarme
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public DateTime? DataDisparado { get; set; }//.This allow you to work with nullable datetime in database.
public DateTime? DataResolvido { get; set; }//.This allow you to work with nullable datetime in database.
public long Latencia { get; set; }
public bool Resolvido { get; set; }
public int SensorId { get; set; }
[ForeignKey("SensorId")]
public virtual Sensor Sensor { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
Kja*_*tan 19
在某些情况下,DateTime.MinValue(或等效地default(DateTime))用于表示未知值.这个简单的扩展方法应该有助于解决问题:
public static class DbDateHelper
{
/// <summary>
/// Replaces any date before 01.01.1753 with a Nullable of
/// DateTime with a value of null.
/// </summary>
/// <param name="date">Date to check</param>
/// <returns>Input date if valid in the DB, or Null if date is
/// too early to be DB compatible.</returns>
public static DateTime? ToNullIfTooEarlyForDb(this DateTime date)
{
return (date >= (DateTime) SqlDateTime.MinValue) ? date : (DateTime?)null;
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
DateTime? dateToPassOnToDb = tooEarlyDate.ToNullIfTooEarlyForDb();
Run Code Online (Sandbox Code Playgroud)
Bri*_*ler 13
如果符合您特定的建模问题,您可以使该字段为空.空日期不会像默认值那样被强制转换为不在SQL DateTime类型范围内的日期.另一个选择是明确映射到不同的类型,也许是,
.HasColumnType("datetime2")
Run Code Online (Sandbox Code Playgroud)
AIM*_*AIM 12
虽然这个问题已经很老了,并且已经有了很好的答案,但我认为我应该再提一个解释这个问题的3种不同方法.
第一种方法
将DateTime属性显式映射public virtual DateTime Start { get; set; }到datetime2表中的相应列.因为默认情况下EF会将其映射到datetime.
这可以通过流畅的API或数据注释来完成.
流畅的API
在DbContext类中包含over OnModelCreating和configure属性Start(出于解释原因,它是EntityClass类的属性).
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Configure only one property
modelBuilder.Entity<EntityClass>()
.Property(e => e.Start)
.HasColumnType("datetime2");
//or configure all DateTime Preperties globally(EF 6 and Above)
modelBuilder.Properties<DateTime>()
.Configure(c => c.HasColumnType("datetime2"));
}
Run Code Online (Sandbox Code Playgroud)数据注释
[Column(TypeName="datetime2")]
public virtual DateTime Start { get; set; }
Run Code Online (Sandbox Code Playgroud)第二种方法
初始化Start为EntityClass构造函数中的默认值.这很好,好像由于某种原因在Start将实体保存到数据库之前未设置值,start将始终具有默认值.确保默认值大于或等于SqlDateTime.MinValue(从1753年1月1日到9999年12月31日)
public class EntityClass
{
public EntityClass()
{
Start= DateTime.Now;
}
public DateTime Start{ get; set; }
}
Run Code Online (Sandbox Code Playgroud)
第三种方法
使之Start成为可以为空的类型DateTime -note ? after DateTime-
public virtual DateTime? Start { get; set; }
Run Code Online (Sandbox Code Playgroud)
有关更多说明,请阅读此文章
如果您的DateTime属性在数据库中可以为空,那么请确保使用DateTime?相关的对象属性,否则EF将传入DateTime.MinValue未分配的值,这些值超出了SQL日期时间类型可以处理的范围.
我的解决方案是将所有datetime列切换到datetime2,并将datetime2用于任何新列.换句话说,默认情况下,EF使用datetime2.将其添加到上下文的OnModelCreating方法:
modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));
Run Code Online (Sandbox Code Playgroud)
这将获得所有DateTime和DateTime?所有实体的属性.