[C#] DbContext 및 SetInitializer를 사용하여 datetime2 범위를 벗어난 변환 오류를 수정하는 방법은 무엇입니까?

Entity Framework 4.1에 도입 된 DbContext 및 Code First API를 사용하고 있습니다.

데이터 모델 과 같은 기본 데이터 유형을 사용 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 파일이 없으므로 수정 방법을 잘 모르겠습니다.

어떤 아이디어?



답변

시작이 SqlDateTime.MinValue (1753 년 1 월 1 일) 이상인지 확인해야합니다. 기본적으로 시작은 DateTime.MinValue (0001 년 1 월 1 일)와 같습니다.


답변

단순한. 먼저 코드에서 DateTime 유형을 DateTime?으로 설정하십시오. 따라서 데이터베이스에서 nullable 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; }
    }


답변

경우에 따라 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;
    }
}

용법:

 DateTime? dateToPassOnToDb = tooEarlyDate.ToNullIfTooEarlyForDb();


답변

특정 모델링 문제에 적합한 경우 필드를 널 입력 가능하게 만들 수 있습니다. 널 날짜는 기본값과 같은 방식으로 SQL DateTime 유형의 범위 내에 있지 않은 날짜로 강제 변환되지 않습니다. 다른 옵션은 다른 유형으로 명시 적으로 매핑하는 것입니다.

.HasColumnType("datetime2")


답변

이 질문은 꽤 오래되었지만 이미 큰 대답이 있지만이 문제를 해결하기 위해 3 가지 접근법을 설명하는 방법을 하나 더 넣어야한다고 생각했습니다.

첫 번째 접근법

테이블의 해당 열에 DateTime속성 public virtual DateTime Start { get; set; }을 명시 적으로 매핑 datetime2합니다. EF는 기본적으로에 매핑하기 때문 datetime입니다.

유창한 API 또는 데이터 주석으로 수행 할 수 있습니다.

  1. 유창한 API

    DbContext 클래스에서 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"));
    }
  2. 데이터 주석

    [Column(TypeName="datetime2")]
    public virtual DateTime Start { get; set; }

두 번째 접근법

StartEntityClass 생성자에서 기본값으로 초기화 합니다. 이것은 어떤 이유로 Start엔티티를 데이터베이스 시작에 저장하기 전에 값이 설정되지 않은 것처럼 항상 기본값을 갖는 것처럼 좋습니다 . 기본값이 SqlDateTime.MinValue 이상인지 확인하십시오 (1753 년 1 월 1 일부터 9999 년 12 월 31 일까지)

public class EntityClass
{
    public EntityClass()
    {
        Start= DateTime.Now;
    }
    public DateTime Start{ get; set; }
}

3 차 접근법

확인 StartNullable 형식의 수 DateTime – 주 ?DateTime

public virtual DateTime? Start { get; set; }

자세한 설명은이 게시물을 읽으십시오


답변

귀하의 경우 DateTime속성이 데이터베이스에 널 (NULL) 후 사용하십시오 DateTime?관련 개체 속성 또는 EF가 전달됩니다 DateTime.MinValue는 SQL이 날짜 형식이 처리 할 수있는 범위의 밖에 할당되지 않은 값.


답변

내 솔루션은 모든 datetime 열을 datetime2로 전환하고 새로운 열에 datetime2를 사용하는 것이 었습니다. 즉, EF가 기본적으로 datetime2를 사용하도록합니다. 컨텍스트의 OnModelCreating 메소드에 이것을 추가하십시오.

modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));

모든 DateTime과 DateTime을 얻을 수 있습니까? 모든 엔티티의 속성.