Как исправить ошибку преобразования datetime2 вне диапазона с помощью DbContext и SetInitializer?
Я использую DbContext и первые API кода, введенные с Entity Framework 4.1.
на модель данных использует базовые типы данных, такие как string
и DateTime
. В некоторых случаях я использую только аннотацию данных [Required]
, но это не на каких-либо DateTime
свойства. Пример:
public virtual DateTime Start { get; set; }
на подкласс DbContext также просто и выглядит так:
public class EventsContext : DbContext
{
public DbSet<Event> Events { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Event>().ToTable("Events");
}
}
на инициализатор устанавливает даты в модель для разумных значений в этом году или в следующем году.
однако, когда я запускаю инициализатор, я получаю эту ошибку в context.SaveChanges()
:
преобразование данных datetime2 тип к типу данных datetime в значении вне диапазона. Этот заявление было прекращено.
Я не понимаю, почему это происходит вовсе не потому, что все так просто. Я также не уверен, как это исправить, так как нет файла edmx для редактировать.
какие идеи?
11 ответов
вы должны убедиться, что Start больше или равен SqlDateTime.MinValue (1 января 1753) - по умолчанию Start равен DateTime.MinValue (1 Января 0001).
простой. В вашем коде сначала установите тип DateTime в DateTime?. Таким образом, вы можете работать с типом DateTime nullable в базе данных. Пример сущности:
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; }
}
В некоторых случаях DateTime.MinValue
(или equivalenly, 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;
}
}
использование:
DateTime? dateToPassOnToDb = tooEarlyDate.ToNullIfTooEarlyForDb();
вы можете сделать поле nullable, если это соответствует вашим конкретным проблемам моделирования. Нулевая дата не будет принуждаться к дате, которая не находится в диапазоне типа SQL DateTime, как значение по умолчанию. Другой вариант-явно сопоставить другой тип, возможно, с,
.HasColumnType("datetime2")
хотя этот вопрос довольно старый и уже есть отличные ответы, я подумал, что должен поставить еще один, который объясняет 3 разных подхода к решению этой проблемы.
1-й подход
явного карте DateTime
свойства public virtual DateTime Start { get; set; }
to datetime2
в соответствующем столбце таблицы. Потому что по умолчанию EF сопоставит его с datetime
.
это можно сделать с помощью fluent API или данных аннотация.
-
свободно API
в классе DbContext overide
OnModelCreating
и настройка собственность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")); }
-
аннотации
[Column(TypeName="datetime2")] public virtual DateTime Start { get; set; }
2-й подход
инициализации Start
к значению по умолчанию в конструкторе EntityClass.Это хорошо, как будто по какой-то причине значение Start
не ставили перед сохранением сущности в базе данных всегда будет иметь значение по умолчанию. Убедитесь, что значение по умолчанию-больше или равно SqlDateTime.Параметр minvalue (с 1 января 1753 года по 31 декабря 9999 года)
public class EntityClass
{
public EntityClass()
{
Start= DateTime.Now;
}
public DateTime Start{ get; set; }
}
3-й подход
сделать Start
быть типа nullable DateTime
Примечание ?
после DateTime
-
public virtual DateTime? Start { get; set; }
более подробное объяснение читайте этот в должности
моим решением было переключить все столбцы datetime на datetime2 и использовать datetime2 для любых новых столбцов. Другими словами, EF использует datetime2 по умолчанию. Добавьте это в метод OnModelCreating в своем контексте:
modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));
Это получит все DateTime и DateTime? свойства всех сущностей.
Если DateTime
свойства nullable в базе данных, то обязательно используйте DateTime?
для связанных свойств объекта или EF пройдет в DateTime.MinValue
для неназначенных значений, которые находятся вне диапазона того, что может обрабатывать тип SQL datetime.
инициализируйте свойство Start в конструкторе
Start = DateTime.Now;
это сработало для меня, когда я пытался добавить несколько новых полей в таблицу пользователей ASP .Net Identity Framework (AspNetUsers), используя сначала код. Я обновил класс-ApplicationUser в IdentityModels.cs и я добавили поле lastLogin типа DateTime.
public class ApplicationUser : IdentityUser
{
public ApplicationUser()
{
CreatedOn = DateTime.Now;
LastPassUpdate = DateTime.Now;
LastLogin = DateTime.Now;
}
public String FirstName { get; set; }
public String MiddleName { get; set; }
public String LastName { get; set; }
public String EmailId { get; set; }
public String ContactNo { get; set; }
public String HintQuestion { get; set; }
public String HintAnswer { get; set; }
public Boolean IsUserActive { get; set; }
//Auditing Fields
public DateTime CreatedOn { get; set; }
public DateTime LastPassUpdate { get; set; }
public DateTime LastLogin { get; set; }
}
У меня была та же проблема, и в моем случае я устанавливал дату на new DateTime() вместо DateTime.Теперь
в моем случае это произошло, когда я использовал entity, а таблица sql имеет значение по умолчанию datetime == getdate(). Итак, что я сделал, чтобы установить значение для этого поля.
сначала я использую базу данных, и когда эта ошибка произошла со мной, моим решением было заставить ProviderManifestToken="2005" в файле edmx (что делает модели совместимыми с SQL Server 2005). Не знаю, возможно ли что-то подобное для кода First.