web-dev-qa-db-ja.com

最初にEntity Frameworkコードを使用してTimeSpanを格納する-SqlDbType.Timeオーバーフロー

私はいくつかの定数を私のDBにシードしようとしています:

context.Stages.AddOrUpdate(s => s.Name,
                                   new Stage()
                                   {
                                       Name = "Seven",
                                       Span = new TimeSpan(2, 0, 0),
                                       StageId = 7
                                   });
context.Stages.AddOrUpdate(s => s.Name,
                                   new Stage()
                                   {
                                       Name = "Eight",
                                       Span = new TimeSpan(1, 0, 0, 0),
                                       StageId = 8
                                   });

これは、EF Codefirst MigrationsのSeed()関数内にあります。次のようにステージ8で失敗します。

System.Data.UpdateException:エントリの更新中にエラーが発生しました。詳細については、内部の例外を参照してください。 ---> System.OverflowException:SqlDbType.Timeオーバーフロー。値「1.00:00:00」は範囲外です。 00:00:00.0000000から23:59:59.9999999の間でなければなりません。

EFを使用してタイムスパンを保存できないのはなぜですか?ここで両端で愚かな時間からティックへの変換を行う必要がないことを本当に願っています...

26
SB2055

この行では:

Span = new TimeSpan(1, 0, 0, 0)

次のコンストラクタを使用しています:

public TimeSpan(int days, int hours, int minutes, int seconds);

つまり、TimeSpanパラメータに1を渡してから24時間を超えるdaysを実際に作成していますが、基になるデータベースタイプはTimeです。 00:00-23:59の値のみを受け入れます。

実際にTimeSpanを1日で使用するつもりだったのか、それとも単なるタイプミスであるのかを判断するのは困難です。

本当に24時間を超えるTimeSpanが必要な場合は、フィールドを別のデータベースタイプ(SmallDateTimeなど)にマップする必要があると思います。

タイプミスだけの場合は、行を次のように変更します。

Span = new TimeSpan(1, 0, 0),
7
haim770
    [Browsable(false)]
    [EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("Property '" + nameof(Duration) + "' should be used instead.")]        
    public long DurationTicks { get; set; }

    [NotMapped]
    public TimeSpan Duration
    {
#pragma warning disable 618
      get { return new TimeSpan(DurationTicks); }
      set { DurationTicks = value.Ticks; }
#pragma warning restore 618
    }

更新

これは、EF Core 2.1以降、 値の変換 を使用して実現可能です。

builder.Entity<Stage>()
    .Property(s => s.Span)
    .HasConversion(new TimeSpanToTicksConverter()); // or TimeSpanToStringConverter
33
Shimmy

前述のように、問題はEFがTimeSpanクラスを24時間に制限されているTimeにマップするという事実です。

24時間を超えるタイムスパンを保存する必要がある場合は、次の2つの方法のいずれかをお勧めします。

1)次のように、タイムスパンのさまざまな要素のintプロパティを使用してTimeSpanエンティティを作成します。

 public class Timespan
{
    public Int64 Id { get; set; }

    public Int16 Years { get; set; }

    public int Months { get; set; }

    public Int64 Days { get; set; }

    public Int64 Hours { get; set; }

    public Int64 Minutes { get; set; }
}

該当するエンティティの外部参照をカスタムTimespanエンティティに追加するだけです。

2)この ブログ投稿 で説明されているように、愚かな時間からティックへの変換を行います。

1
user3083619